synapsecns/sanguine

View on GitHub
agents/contracts/origin/origin.contractinfo.json

Summary

Maintainability
Test Coverage
{"solidity/Origin.sol:AddressUpgradeable":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212203fbdb20387c8a49e56e558f685db0c98c0f8d975506fcb369e339e22056829b164736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212203fbdb20387c8a49e56e558f685db0c98c0f8d975506fcb369e339e22056829b164736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/OriginEvents.sol\n\n/// @notice A collection of events emitted by the Origin contract\nabstract contract OriginEvents {\n    /**\n     * @notice Emitted when a new message is sent.\n     * @param messageHash   Hash of message; the leaf inserted to the Merkle tree for the message\n     * @param nonce         Nonce of sent message (starts from 1)\n     * @param destination   Destination domain\n     * @param message       Raw bytes of message\n     */\n    event Sent(bytes32 indexed messageHash, uint32 indexed nonce, uint32 indexed destination, bytes message);\n\n    /**\n     * @notice Emitted when a tip withdrawal is completed.\n     * @param actor     Actor address\n     * @param tip       Tip value, denominated in local domain's wei\n     */\n    event TipWithdrawalCompleted(address actor, uint256 tip);\n}\n\n// contracts/events/StateHubEvents.sol\n\n/// @notice A collection of events emitted by the StateHub contract\nabstract contract StateHubEvents {\n    /**\n     * @notice Emitted when a new Origin State is saved after a message was sent.\n     * @param state     Raw payload with state data\n     */\n    event StateSaved(bytes state);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n    /**\n     * @notice Check that a given state is valid: matches the historical state of Origin contract.\n     * Note: any Agent including an invalid state in their snapshot will be slashed\n     * upon providing the snapshot and agent signature for it to Origin contract.\n     * @dev Will revert if any of these is true:\n     *  - State payload is not properly formatted.\n     * @param statePayload      Raw payload with state data\n     * @return isValid          Whether the provided state is valid\n     */\n    function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns the amount of saved states so far.\n     * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n     */\n    function statesAmount() external view returns (uint256);\n\n    /**\n     * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @return statePayload     Raw payload with the latest state data\n     */\n    function suggestLatestState() external view returns (bytes memory statePayload);\n\n    /**\n     * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @param nonce             Historical nonce to form a state\n     * @return statePayload     Raw payload with historical state data\n     */\n    function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/InterfaceGasOracle.sol\n\ninterface InterfaceGasOracle {\n    /**\n     * @notice Fetches the latest gas data for the chain from `Destination` contract,\n     * and uses it to update the oracle values for the requested chain.\n     * @param domain    Domain to update the gas data for\n     */\n    function updateGasData(uint32 domain) external;\n\n    /**\n     * @notice Returns the gas data for the local chain.\n     */\n    function getGasData() external view returns (uint256 paddedGasData);\n\n    /**\n     * @notice Returns the gas data for the given domain, in the decoded format.\n     * @param domain        Domain of chain to get gas data for\n     * @return gasPrice     Gas price for the chain (in Wei per gas unit)\n     * @return dataPrice    Calldata price (in Wei per byte of content)\n     * @return execBuffer   Tx fee safety buffer for message execution (in Wei)\n     * @return amortAttCost Amortized cost for attestation submission (in Wei)\n     * @return etherPrice   Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n     * @return markup       Markup for the message execution (in BWAD)\n     */\n    function getDecodedGasData(uint32 domain)\n        external\n        view\n        returns (\n            uint256 gasPrice,\n            uint256 dataPrice,\n            uint256 execBuffer,\n            uint256 amortAttCost,\n            uint256 etherPrice,\n            uint256 markup\n        );\n\n    /**\n     * @notice Returns the minimum tips for sending a message to a given destination.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return paddedTips       Padded encoded minimum tips information\n     */\n    function getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 paddedTips);\n}\n\n// contracts/interfaces/InterfaceOrigin.sol\n\ninterface InterfaceOrigin {\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /**\n     * @notice Send a message to the recipient located on destination domain.\n     * @dev Recipient has to conform to IMessageRecipient interface, otherwise message won't be delivered.\n     * Will revert if any of these is true:\n     * - `destination` is equal to contract's local domain\n     * - `content` length is greater than `MAX_CONTENT_BYTES`\n     * - `msg.value` is lower than value of minimum tips for the given message\n     * @param destination           Domain of destination chain\n     * @param recipient             Address of recipient on destination chain as bytes32\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param paddedRequest         Padded encoded message execution request on destination chain\n     * @param content               Raw bytes content of message\n     * @return messageNonce         Nonce of the sent message\n     * @return messageHash          Hash of the sent message\n     */\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable returns (uint32 messageNonce, bytes32 messageHash);\n\n    /**\n     * @notice Send a manager message to the destination domain.\n     * @dev This could only be called by AgentManager, which takes care of encoding the calldata payload.\n     * Note: (msgOrigin, proofMaturity) security args will be added to payload on the destination chain\n     * so that the AgentManager could verify where the Manager Message came from and how mature is the proof.\n     * Note: function is not payable, as no tips are required for sending a manager message.\n     * Will revert if `destination` is equal to contract's local domain.\n     * @param destination           Domain of destination chain\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param payload               Payload for calling AgentManager on destination chain (with extra security args)\n     */\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        returns (uint32 messageNonce, bytes32 messageHash);\n\n    // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Withdraws locked base message tips to the recipient.\n     * @dev Could only be called by a local AgentManager.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function withdrawTips(address recipient, uint256 amount) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the minimum tips value for sending a message to a given destination.\n     * @dev Using at least `tipsValue` as `msg.value` for `sendBaseMessage()`\n     * will guarantee that the message will be accepted.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return tipsValue        Minimum tips value for a message to be accepted\n     */\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue);\n}\n\n// contracts/libs/Constants.sol\n\n// Here we define common constants to enable their easier reusing later.\n\n// ══════════════════════════════════ MERKLE ═══════════════════════════════════\n/// @dev Height of the Agent Merkle Tree\nuint256 constant AGENT_TREE_HEIGHT = 32;\n/// @dev Height of the Origin Merkle Tree\nuint256 constant ORIGIN_TREE_HEIGHT = 32;\n/// @dev Height of the Snapshot Merkle Tree. Allows up to 64 leafs, e.g. up to 32 states\nuint256 constant SNAPSHOT_TREE_HEIGHT = 6;\n// ══════════════════════════════════ STRUCTS ══════════════════════════════════\n/// @dev See Attestation.sol: (bytes32,bytes32,uint32,uint40,uint40): 32+32+4+5+5\nuint256 constant ATTESTATION_LENGTH = 78;\n/// @dev See GasData.sol: (uint16,uint16,uint16,uint16,uint16,uint16): 2+2+2+2+2+2\nuint256 constant GAS_DATA_LENGTH = 12;\n/// @dev See Receipt.sol: (uint32,uint32,bytes32,bytes32,uint8,address,address,address): 4+4+32+32+1+20+20+20\nuint256 constant RECEIPT_LENGTH = 133;\n/// @dev See State.sol: (bytes32,uint32,uint32,uint40,uint40,GasData): 32+4+4+5+5+len(GasData)\nuint256 constant STATE_LENGTH = 50 + GAS_DATA_LENGTH;\n/// @dev Maximum amount of states in a single snapshot. Each state produces two leafs in the tree\nuint256 constant SNAPSHOT_MAX_STATES = 1 \u003c\u003c (SNAPSHOT_TREE_HEIGHT - 1);\n// ══════════════════════════════════ MESSAGE ══════════════════════════════════\n/// @dev See Header.sol: (uint8,uint32,uint32,uint32,uint32): 1+4+4+4+4\nuint256 constant HEADER_LENGTH = 17;\n/// @dev See Request.sol: (uint96,uint64,uint32): 12+8+4\nuint256 constant REQUEST_LENGTH = 24;\n/// @dev See Tips.sol: (uint64,uint64,uint64,uint64): 8+8+8+8\nuint256 constant TIPS_LENGTH = 32;\n/// @dev The amount of discarded last bits when encoding tip values\nuint256 constant TIPS_GRANULARITY = 32;\n/// @dev Tip values could be only the multiples of TIPS_MULTIPLIER\nuint256 constant TIPS_MULTIPLIER = 1 \u003c\u003c TIPS_GRANULARITY;\n// ══════════════════════════════ STATEMENT SALTS ══════════════════════════════\n/// @dev Salts for signing various statements\nbytes32 constant ATTESTATION_VALID_SALT = keccak256(\"ATTESTATION_VALID_SALT\");\nbytes32 constant ATTESTATION_INVALID_SALT = keccak256(\"ATTESTATION_INVALID_SALT\");\nbytes32 constant RECEIPT_VALID_SALT = keccak256(\"RECEIPT_VALID_SALT\");\nbytes32 constant RECEIPT_INVALID_SALT = keccak256(\"RECEIPT_INVALID_SALT\");\nbytes32 constant SNAPSHOT_VALID_SALT = keccak256(\"SNAPSHOT_VALID_SALT\");\nbytes32 constant STATE_INVALID_SALT = keccak256(\"STATE_INVALID_SALT\");\n// ═════════════════════════════════ PROTOCOL ══════════════════════════════════\n/// @dev Optimistic period for new agent roots in LightManager\nuint32 constant AGENT_ROOT_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Timeout between the agent root could be proposed and resolved in LightManager\nuint32 constant AGENT_ROOT_PROPOSAL_TIMEOUT = 12 hours;\nuint32 constant BONDING_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Amount of time that the Notary will not be considered active after they won a dispute\nuint32 constant DISPUTE_TIMEOUT_NOTARY = 12 hours;\n/// @dev Amount of time without fresh data from Notaries before contract owner can resolve stuck disputes manually\nuint256 constant FRESH_DATA_TIMEOUT = 4 hours;\n/// @dev Maximum bytes per message = 2 KiB (somewhat arbitrarily set to begin)\nuint256 constant MAX_CONTENT_BYTES = 2 * 2 ** 10;\n/// @dev Maximum value for the summit tip that could be set in GasOracle\nuint256 constant MAX_SUMMIT_TIP = 0.01 ether;\n\n// contracts/libs/Errors.sol\n\n// ══════════════════════════════ INVALID CALLER ═══════════════════════════════\n\nerror CallerNotAgentManager();\nerror CallerNotDestination();\nerror CallerNotInbox();\nerror CallerNotSummit();\n\n// ══════════════════════════════ INCORRECT DATA ═══════════════════════════════\n\nerror IncorrectAttestation();\nerror IncorrectAgentDomain();\nerror IncorrectAgentIndex();\nerror IncorrectAgentProof();\nerror IncorrectAgentRoot();\nerror IncorrectDataHash();\nerror IncorrectDestinationDomain();\nerror IncorrectOriginDomain();\nerror IncorrectSnapshotProof();\nerror IncorrectSnapshotRoot();\nerror IncorrectState();\nerror IncorrectStatesAmount();\nerror IncorrectTipsProof();\nerror IncorrectVersionLength();\n\nerror IncorrectNonce();\nerror IncorrectSender();\nerror IncorrectRecipient();\n\nerror FlagOutOfRange();\nerror IndexOutOfRange();\nerror NonceOutOfRange();\n\nerror OutdatedNonce();\n\nerror UnformattedAttestation();\nerror UnformattedAttestationReport();\nerror UnformattedBaseMessage();\nerror UnformattedCallData();\nerror UnformattedCallDataPrefix();\nerror UnformattedMessage();\nerror UnformattedReceipt();\nerror UnformattedReceiptReport();\nerror UnformattedSignature();\nerror UnformattedSnapshot();\nerror UnformattedState();\nerror UnformattedStateReport();\n\n// ═══════════════════════════════ MERKLE TREES ════════════════════════════════\n\nerror LeafNotProven();\nerror MerkleTreeFull();\nerror NotEnoughLeafs();\nerror TreeHeightTooLow();\n\n// ═════════════════════════════ OPTIMISTIC PERIOD ═════════════════════════════\n\nerror BaseClientOptimisticPeriod();\nerror MessageOptimisticPeriod();\nerror SlashAgentOptimisticPeriod();\nerror WithdrawTipsOptimisticPeriod();\nerror ZeroProofMaturity();\n\n// ═══════════════════════════════ AGENT MANAGER ═══════════════════════════════\n\nerror AgentNotGuard();\nerror AgentNotNotary();\n\nerror AgentCantBeAdded();\nerror AgentNotActive();\nerror AgentNotActiveNorUnstaking();\nerror AgentNotFraudulent();\nerror AgentNotUnstaking();\nerror AgentUnknown();\n\nerror AgentRootNotProposed();\nerror AgentRootTimeoutNotOver();\n\nerror NotStuck();\n\nerror DisputeAlreadyResolved();\nerror DisputeNotOpened();\nerror DisputeTimeoutNotOver();\nerror GuardInDispute();\nerror NotaryInDispute();\n\nerror MustBeSynapseDomain();\nerror SynapseDomainForbidden();\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\nerror AlreadyExecuted();\nerror AlreadyFailed();\nerror DuplicatedSnapshotRoot();\nerror IncorrectMagicValue();\nerror GasLimitTooLow();\nerror GasSuppliedTooLow();\n\n// ══════════════════════════════════ ORIGIN ═══════════════════════════════════\n\nerror ContentLengthTooBig();\nerror EthTransferFailed();\nerror InsufficientEthBalance();\n\n// ════════════════════════════════ GAS ORACLE ═════════════════════════════════\n\nerror LocalGasDataNotSet();\nerror RemoteGasDataNotSet();\n\n// ═══════════════════════════════════ TIPS ════════════════════════════════════\n\nerror SummitTipTooHigh();\nerror TipsClaimMoreThanEarned();\nerror TipsClaimZero();\nerror TipsOverflow();\nerror TipsValueTooLow();\n\n// ════════════════════════════════ MEMORY VIEW ════════════════════════════════\n\nerror IndexedTooMuch();\nerror ViewOverrun();\nerror OccupiedMemory();\nerror UnallocatedMemory();\nerror PrecompileOutOfGas();\n\n// ═════════════════════════════════ MULTICALL ═════════════════════════════════\n\nerror MulticallFailed();\n\n// contracts/libs/TypeCasts.sol\n\nlibrary TypeCasts {\n    // alignment preserving cast\n    function addressToBytes32(address addr) internal pure returns (bytes32) {\n        return bytes32(uint256(uint160(addr)));\n    }\n\n    // alignment preserving cast\n    function bytes32ToAddress(bytes32 buf) internal pure returns (address) {\n        return address(uint160(uint256(buf)));\n    }\n}\n\n// contracts/libs/stack/Number.sol\n\n/// Number is a compact representation of uint256, that is fit into 16 bits\n/// with the maximum relative error under 0.4%.\ntype Number is uint16;\n\nusing NumberLib for Number global;\n\n/// # Number\n/// Library for compact representation of uint256 numbers.\n/// - Number is stored using mantissa and exponent, each occupying 8 bits.\n/// - Numbers under 2**8 are stored as `mantissa` with `exponent = 0xFF`.\n/// - Numbers at least 2**8 are approximated as `(256 + mantissa) \u003c\u003c exponent`\n/// \u003e - `0 \u003c= mantissa \u003c 256`\n/// \u003e - `0 \u003c= exponent \u003c= 247` (`256 * 2**248` doesn't fit into uint256)\n/// # Number stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type  | Bytes |\n/// | ---------- | -------- | ----- | ----- |\n/// | (002..001] | mantissa | uint8 | 1     |\n/// | (001..000] | exponent | uint8 | 1     |\n\nlibrary NumberLib {\n    /// @dev Amount of bits to shift to mantissa field\n    uint16 private constant SHIFT_MANTISSA = 8;\n\n    /// @notice For bwad math (binary wad) we use 2**64 as \"wad\" unit.\n    /// @dev We are using not using 10**18 as wad, because it is not stored precisely in NumberLib.\n    uint256 internal constant BWAD_SHIFT = 64;\n    uint256 internal constant BWAD = 1 \u003c\u003c BWAD_SHIFT;\n    /// @notice ~0.1% in bwad units.\n    uint256 internal constant PER_MILLE_SHIFT = BWAD_SHIFT - 10;\n    uint256 internal constant PER_MILLE = 1 \u003c\u003c PER_MILLE_SHIFT;\n\n    /// @notice Compresses uint256 number into 16 bits.\n    function compress(uint256 value) internal pure returns (Number) {\n        // Find `msb` such as `2**msb \u003c= value \u003c 2**(msb + 1)`\n        uint256 msb = mostSignificantBit(value);\n        // We want to preserve 9 bits of precision.\n        // The highest bit is always 1, so we can skip it.\n        // The remaining 8 highest bits are stored as mantissa.\n        if (msb \u003c 8) {\n            // Value is less than 2**8, so we can use value as mantissa with \"-1\" exponent.\n            return _encode(uint8(value), 0xFF);\n        } else {\n            // We use `msb - 8` as exponent otherwise. Note that `exponent \u003e= 0`.\n            unchecked {\n                uint256 exponent = msb - 8;\n                // Shifting right by `msb-8` bits will shift the \"remaining 8 highest bits\" into the 8 lowest bits.\n                // uint8() will truncate the highest bit.\n                return _encode(uint8(value \u003e\u003e exponent), uint8(exponent));\n            }\n        }\n    }\n\n    /// @notice Decompresses 16 bits number into uint256.\n    /// @dev The outcome is an approximation of the original number: `(value - value / 256) \u003c number \u003c= value`.\n    function decompress(Number number) internal pure returns (uint256 value) {\n        // Isolate 8 highest bits as the mantissa.\n        uint256 mantissa = Number.unwrap(number) \u003e\u003e SHIFT_MANTISSA;\n        // This will truncate the highest bits, leaving only the exponent.\n        uint256 exponent = uint8(Number.unwrap(number));\n        if (exponent == 0xFF) {\n            return mantissa;\n        } else {\n            unchecked {\n                return (256 + mantissa) \u003c\u003c (exponent);\n            }\n        }\n    }\n\n    /// @dev Returns the most significant bit of `x`\n    /// https://solidity-by-example.org/bitwise/\n    function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\n        // To find `msb` we determine it bit by bit, starting from the highest one.\n        // `0 \u003c= msb \u003c= 255`, so we start from the highest bit, 1\u003c\u003c7 == 128.\n        // If `x` is at least 2**128, then the highest bit of `x` is at least 128.\n        // solhint-disable no-inline-assembly\n        assembly {\n            // `f` is set to 1\u003c\u003c7 if `x \u003e= 2**128` and to 0 otherwise.\n            let f := shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\n            // If `x \u003e= 2**128` then set `msb` highest bit to 1 and shift `x` right by 128.\n            // Otherwise, `msb` remains 0 and `x` remains unchanged.\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        // `x` is now at most 2**128 - 1. Continue the same way, the next highest bit is 1\u003c\u003c6 == 64.\n        assembly {\n            // `f` is set to 1\u003c\u003c6 if `x \u003e= 2**64` and to 0 otherwise.\n            let f := shl(6, gt(x, 0xFFFFFFFFFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c5 if `x \u003e= 2**32` and to 0 otherwise.\n            let f := shl(5, gt(x, 0xFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c4 if `x \u003e= 2**16` and to 0 otherwise.\n            let f := shl(4, gt(x, 0xFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c3 if `x \u003e= 2**8` and to 0 otherwise.\n            let f := shl(3, gt(x, 0xFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c2 if `x \u003e= 2**4` and to 0 otherwise.\n            let f := shl(2, gt(x, 0xF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c1 if `x \u003e= 2**2` and to 0 otherwise.\n            let f := shl(1, gt(x, 0x3))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1 if `x \u003e= 2**1` and to 0 otherwise.\n            let f := gt(x, 0x1)\n            msb := or(msb, f)\n        }\n    }\n\n    /// @dev Wraps (mantissa, exponent) pair into Number.\n    function _encode(uint8 mantissa, uint8 exponent) private pure returns (Number) {\n        // Casts below are upcasts, so they are safe.\n        return Number.wrap(uint16(mantissa) \u003c\u003c SHIFT_MANTISSA | uint16(exponent));\n    }\n}\n\n// contracts/libs/stack/Request.sol\n\n/// Request is encoded data with \"message execution request\".\ntype Request is uint192;\n\nusing RequestLib for Request global;\n\n/// Library for formatting _the request part_ of _the base messages_.\n/// - Request represents a message sender requirements for the message execution on the destination chain.\n/// - Request occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n/// \u003e gasDrop field is included for future compatibility and is ignored at the moment.\n///\n/// # Request stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type   | Bytes | Description                                          |\n/// | ---------- | -------- | ------ | ----- | ---------------------------------------------------- |\n/// | (024..012] | gasDrop  | uint96 | 12    | Minimum amount of gas token to drop to the recipient |\n/// | (012..004] | gasLimit | uint64 | 8     | Minimum amount of gas units to supply for execution  |\n/// | (004..000] | version  | uint32 | 4     | Base message version to pass to the recipient        |\n\nlibrary RequestLib {\n    /// @dev Amount of bits to shift to gasDrop field\n    uint192 private constant SHIFT_GAS_DROP = 12 * 8;\n    /// @dev Amount of bits to shift to gasLimit field\n    uint192 private constant SHIFT_GAS_LIMIT = 4 * 8;\n\n    /// @notice Returns an encoded request with the given fields\n    /// @param gasDrop_     Minimum amount of gas token to drop to the recipient (ignored at the moment)\n    /// @param gasLimit_    Minimum amount of gas units to supply for execution\n    /// @param version_     Base message version to pass to the recipient\n    function encodeRequest(uint96 gasDrop_, uint64 gasLimit_, uint32 version_) internal pure returns (Request) {\n        // Casts below are upcasts, so they are safe\n        return Request.wrap(uint192(gasDrop_) \u003c\u003c SHIFT_GAS_DROP | uint192(gasLimit_) \u003c\u003c SHIFT_GAS_LIMIT | version_);\n    }\n\n    /// @notice Wraps the padded encoded request into a Request-typed value.\n    /// @dev The \"padded\" request is simply an encoded request casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded requests\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedRequest) internal pure returns (Request) {\n        // Casting to uint192 will truncate the highest bits, which is the behavior we want\n        return Request.wrap(uint192(paddedRequest));\n    }\n\n    /// @notice Returns the requested of gas token to drop to the recipient.\n    function gasDrop(Request request) internal pure returns (uint96) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return uint96(Request.unwrap(request) \u003e\u003e SHIFT_GAS_DROP);\n    }\n\n    /// @notice Returns the requested minimum amount of gas units to supply for execution.\n    function gasLimit(Request request) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Request.unwrap(request) \u003e\u003e SHIFT_GAS_LIMIT);\n    }\n\n    /// @notice Returns the requested base message version to pass to the recipient.\n    function version(Request request) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Request.unwrap(request));\n    }\n}\n\n// node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        require(value \u003c= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        require(value \u003c= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        require(value \u003c= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value \u003c= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        require(value \u003c= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        require(value \u003c= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        require(value \u003c= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        require(value \u003c= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        require(value \u003c= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        require(value \u003c= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        require(value \u003c= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        require(value \u003c= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        require(value \u003c= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        require(value \u003c= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        require(value \u003c= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value \u003c= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        require(value \u003c= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        require(value \u003c= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        require(value \u003c= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value \u003c= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        require(value \u003c= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        require(value \u003c= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        require(value \u003c= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value \u003c= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        require(value \u003c= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        require(value \u003c= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        require(value \u003c= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value \u003c= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        require(value \u003c= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value \u003c= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value \u003c= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     *\n     * _Available since v3.0._\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value \u003e= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     *\n     * _Available since v3.0._\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value \u003c= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     *\n     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length \u003e 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance \u003e= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance \u003e= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length \u003e 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n\n// contracts/base/MultiCallable.sol\n\n/// @notice Collection of Multicall utilities. Fork of Multicall3:\n/// https://github.com/mds1/multicall/blob/master/src/Multicall3.sol\nabstract contract MultiCallable {\n    struct Call {\n        bool allowFailure;\n        bytes callData;\n    }\n\n    struct Result {\n        bool success;\n        bytes returnData;\n    }\n\n    /// @notice Aggregates a few calls to this contract into one multicall without modifying `msg.sender`.\n    function multicall(Call[] calldata calls) external returns (Result[] memory callResults) {\n        uint256 amount = calls.length;\n        callResults = new Result[](amount);\n        Call calldata call_;\n        for (uint256 i = 0; i \u003c amount;) {\n            call_ = calls[i];\n            Result memory result = callResults[i];\n            // We perform a delegate call to ourselves here. Delegate call does not modify `msg.sender`, so\n            // this will have the same effect as if `msg.sender` performed all the calls themselves one by one.\n            // solhint-disable-next-line avoid-low-level-calls\n            (result.success, result.returnData) = address(this).delegatecall(call_.callData);\n            // solhint-disable-next-line no-inline-assembly\n            assembly {\n                // Revert if the call fails and failure is not allowed\n                // `allowFailure := calldataload(call_)` and `success := mload(result)`\n                if iszero(or(calldataload(call_), mload(result))) {\n                    // Revert with `0x4d6a2328` (function selector for `MulticallFailed()`)\n                    mstore(0x00, 0x4d6a232800000000000000000000000000000000000000000000000000000000)\n                    revert(0x00, 0x04)\n                }\n            }\n            unchecked {\n                ++i;\n            }\n        }\n    }\n}\n\n// contracts/base/Version.sol\n\n/**\n * @title Versioned\n * @notice Version getter for contracts. Doesn't use any storage slots, meaning\n * it will never cause any troubles with the upgradeable contracts. For instance, this contract\n * can be added or removed from the inheritance chain without shifting the storage layout.\n */\nabstract contract Versioned {\n    /**\n     * @notice Struct that is mimicking the storage layout of a string with 32 bytes or less.\n     * Length is limited by 32, so the whole string payload takes two memory words:\n     * @param length    String length\n     * @param data      String characters\n     */\n    struct _ShortString {\n        uint256 length;\n        bytes32 data;\n    }\n\n    /// @dev Length of the \"version string\"\n    uint256 private immutable _length;\n    /// @dev Bytes representation of the \"version string\".\n    /// Strings with length over 32 are not supported!\n    bytes32 private immutable _data;\n\n    constructor(string memory version_) {\n        _length = bytes(version_).length;\n        if (_length \u003e 32) revert IncorrectVersionLength();\n        // bytes32 is left-aligned =\u003e this will store the byte representation of the string\n        // with the trailing zeroes to complete the 32-byte word\n        _data = bytes32(bytes(version_));\n    }\n\n    function version() external view returns (string memory versionString) {\n        // Load the immutable values to form the version string\n        _ShortString memory str = _ShortString(_length, _data);\n        // The only way to do this cast is doing some dirty assembly\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            versionString := str\n        }\n    }\n}\n\n// contracts/libs/ChainContext.sol\n\n/// @notice Library for accessing chain context variables as tightly packed integers.\n/// Messaging contracts should rely on this library for accessing chain context variables\n/// instead of doing the casting themselves.\nlibrary ChainContext {\n    using SafeCast for uint256;\n\n    /// @notice Returns the current block number as uint40.\n    /// @dev Reverts if block number is greater than 40 bits, which is not supposed to happen\n    /// until the block.timestamp overflows (assuming block time is at least 1 second).\n    function blockNumber() internal view returns (uint40) {\n        return block.number.toUint40();\n    }\n\n    /// @notice Returns the current block timestamp as uint40.\n    /// @dev Reverts if block timestamp is greater than 40 bits, which is\n    /// supposed to happen approximately in year 36835.\n    function blockTimestamp() internal view returns (uint40) {\n        return block.timestamp.toUint40();\n    }\n\n    /// @notice Returns the chain id as uint32.\n    /// @dev Reverts if chain id is greater than 32 bits, which is not\n    /// supposed to happen in production.\n    function chainId() internal view returns (uint32) {\n        return block.chainid.toUint32();\n    }\n}\n\n// contracts/libs/Structures.sol\n\n// Here we define common enums and structures to enable their easier reusing later.\n\n// ═══════════════════════════════ AGENT STATUS ════════════════════════════════\n\n/// @dev Potential statuses for the off-chain bonded agent:\n/// - Unknown: never provided a bond =\u003e signature not valid\n/// - Active: has a bond in BondingManager =\u003e signature valid\n/// - Unstaking: has a bond in BondingManager, initiated the unstaking =\u003e signature not valid\n/// - Resting: used to have a bond in BondingManager, successfully unstaked =\u003e signature not valid\n/// - Fraudulent: proven to commit fraud, value in Merkle Tree not updated =\u003e signature not valid\n/// - Slashed: proven to commit fraud, value in Merkle Tree was updated =\u003e signature not valid\n/// Unstaked agent could later be added back to THE SAME domain by staking a bond again.\n/// Honest agent: Unknown -\u003e Active -\u003e unstaking -\u003e Resting -\u003e Active ...\n/// Malicious agent: Unknown -\u003e Active -\u003e Fraudulent -\u003e Slashed\n/// Malicious agent: Unknown -\u003e Active -\u003e Unstaking -\u003e Fraudulent -\u003e Slashed\nenum AgentFlag {\n    Unknown,\n    Active,\n    Unstaking,\n    Resting,\n    Fraudulent,\n    Slashed\n}\n\n/// @notice Struct for storing an agent in the BondingManager contract.\nstruct AgentStatus {\n    AgentFlag flag;\n    uint32 domain;\n    uint32 index;\n}\n// 184 bits available for tight packing\n\nusing StructureUtils for AgentStatus global;\n\n/// @notice Potential statuses of an agent in terms of being in dispute\n/// - None: agent is not in dispute\n/// - Pending: agent is in unresolved dispute\n/// - Slashed: agent was in dispute that lead to agent being slashed\n/// Note: agent who won the dispute has their status reset to None\nenum DisputeFlag {\n    None,\n    Pending,\n    Slashed\n}\n\n/// @notice Struct for storing dispute status of an agent.\n/// @param flag         Dispute flag: None/Pending/Slashed.\n/// @param openedAt     Timestamp when the latest agent dispute was opened (zero if not opened).\n/// @param resolvedAt   Timestamp when the latest agent dispute was resolved (zero if not resolved).\nstruct DisputeStatus {\n    DisputeFlag flag;\n    uint40 openedAt;\n    uint40 resolvedAt;\n}\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\n/// @notice Struct representing the status of Destination contract.\n/// @param snapRootTime     Timestamp when latest snapshot root was accepted\n/// @param agentRootTime    Timestamp when latest agent root was accepted\n/// @param notaryIndex      Index of Notary who signed the latest agent root\nstruct DestinationStatus {\n    uint40 snapRootTime;\n    uint40 agentRootTime;\n    uint32 notaryIndex;\n}\n\n// ═══════════════════════════════ EXECUTION HUB ═══════════════════════════════\n\n/// @notice Potential statuses of the message in Execution Hub.\n/// - None: there hasn't been a valid attempt to execute the message yet\n/// - Failed: there was a valid attempt to execute the message, but recipient reverted\n/// - Success: there was a valid attempt to execute the message, and recipient did not revert\n/// Note: message can be executed until its status is Success\nenum MessageStatus {\n    None,\n    Failed,\n    Success\n}\n\nlibrary StructureUtils {\n    /// @notice Checks that Agent is Active\n    function verifyActive(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active) {\n            revert AgentNotActive();\n        }\n    }\n\n    /// @notice Checks that Agent is Unstaking\n    function verifyUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Unstaking) {\n            revert AgentNotUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Active or Unstaking\n    function verifyActiveUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active \u0026\u0026 status.flag != AgentFlag.Unstaking) {\n            revert AgentNotActiveNorUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Fraudulent\n    function verifyFraudulent(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Fraudulent) {\n            revert AgentNotFraudulent();\n        }\n    }\n\n    /// @notice Checks that Agent is not Unknown\n    function verifyKnown(AgentStatus memory status) internal pure {\n        if (status.flag == AgentFlag.Unknown) {\n            revert AgentUnknown();\n        }\n    }\n}\n\n// contracts/libs/memory/MemView.sol\n\n/// @dev MemView is an untyped view over a portion of memory to be used instead of `bytes memory`\ntype MemView is uint256;\n\n/// @dev Attach library functions to MemView\nusing MemViewLib for MemView global;\n\n/// @notice Library for operations with the memory views.\n/// Forked from https://github.com/summa-tx/memview-sol with several breaking changes:\n/// - The codebase is ported to Solidity 0.8\n/// - Custom errors are added\n/// - The runtime type checking is replaced with compile-time check provided by User-Defined Value Types\n///   https://docs.soliditylang.org/en/latest/types.html#user-defined-value-types\n/// - uint256 is used as the underlying type for the \"memory view\" instead of bytes29.\n///   It is wrapped into MemView custom type in order not to be confused with actual integers.\n/// - Therefore the \"type\" field is discarded, allowing to allocate 16 bytes for both view location and length\n/// - The documentation is expanded\n/// - Library functions unused by the rest of the codebase are removed\n//  - Very pretty code separators are added :)\nlibrary MemViewLib {\n    /// @notice Stack layout for uint256 (from highest bits to lowest)\n    /// (32 .. 16]      loc     16 bytes    Memory address of underlying bytes\n    /// (16 .. 00]      len     16 bytes    Length of underlying bytes\n\n    // ═══════════════════════════════════════════ BUILDING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Instantiate a new untyped memory view. This should generally not be called directly.\n     * Prefer `ref` wherever possible.\n     * @param loc_          The memory address\n     * @param len_          The length\n     * @return The new view with the specified location and length\n     */\n    function build(uint256 loc_, uint256 len_) internal pure returns (MemView) {\n        uint256 end_ = loc_ + len_;\n        // Make sure that a view is not constructed that points to unallocated memory\n        // as this could be indicative of a buffer overflow attack\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            if gt(end_, mload(0x40)) { end_ := 0 }\n        }\n        if (end_ == 0) {\n            revert UnallocatedMemory();\n        }\n        return _unsafeBuildUnchecked(loc_, len_);\n    }\n\n    /**\n     * @notice Instantiate a memory view from a byte array.\n     * @dev Note that due to Solidity memory representation, it is not possible to\n     * implement a deref, as the `bytes` type stores its len in memory.\n     * @param arr           The byte array\n     * @return The memory view over the provided byte array\n     */\n    function ref(bytes memory arr) internal pure returns (MemView) {\n        uint256 len_ = arr.length;\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 loc_;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // We add 0x20, so that the view starts exactly where the array data starts\n            loc_ := add(arr, 0x20)\n        }\n        return build(loc_, len_);\n    }\n\n    // ════════════════════════════════════════════ CLONING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to the new memory.\n     * @param memView       The memory view\n     * @return arr          The cloned byte array\n     */\n    function clone(MemView memView) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        unchecked {\n            _unsafeCopyTo(memView, ptr + 0x20);\n        }\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 len_ = memView.len();\n        uint256 footprint_ = memView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    /**\n     * @notice Copies all views, joins them into a new bytearray.\n     * @param memViews      The memory views\n     * @return arr          The new byte array with joined data behind the given views\n     */\n    function join(MemView[] memory memViews) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        MemView newView;\n        unchecked {\n            newView = _unsafeJoin(memViews, ptr + 0x20);\n        }\n        uint256 len_ = newView.len();\n        uint256 footprint_ = newView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    // ══════════════════════════════════════════ INSPECTING MEMORY VIEW ═══════════════════════════════════════════════\n\n    /**\n     * @notice Returns the memory address of the underlying bytes.\n     * @param memView       The memory view\n     * @return loc_         The memory address\n     */\n    function loc(MemView memView) internal pure returns (uint256 loc_) {\n        // loc is stored in the highest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u003e\u003e 128;\n    }\n\n    /**\n     * @notice Returns the number of bytes of the view.\n     * @param memView       The memory view\n     * @return len_         The length of the view\n     */\n    function len(MemView memView) internal pure returns (uint256 len_) {\n        // len is stored in the lowest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u0026 type(uint128).max;\n    }\n\n    /**\n     * @notice Returns the endpoint of `memView`.\n     * @param memView       The memory view\n     * @return end_         The endpoint of `memView`\n     */\n    function end(MemView memView) internal pure returns (uint256 end_) {\n        // The endpoint never overflows uint128, let alone uint256, so we could use unchecked math here\n        unchecked {\n            return memView.loc() + memView.len();\n        }\n    }\n\n    /**\n     * @notice Returns the number of memory words this memory view occupies, rounded up.\n     * @param memView       The memory view\n     * @return words_       The number of memory words\n     */\n    function words(MemView memView) internal pure returns (uint256 words_) {\n        // returning ceil(length / 32.0)\n        unchecked {\n            return (memView.len() + 31) \u003e\u003e 5;\n        }\n    }\n\n    /**\n     * @notice Returns the in-memory footprint of a fresh copy of the view.\n     * @param memView       The memory view\n     * @return footprint_   The in-memory footprint of a fresh copy of the view.\n     */\n    function footprint(MemView memView) internal pure returns (uint256 footprint_) {\n        // words() * 32\n        return memView.words() \u003c\u003c 5;\n    }\n\n    // ════════════════════════════════════════════ HASHING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the keccak256 hash of the underlying memory\n     * @param memView       The memory view\n     * @return digest       The keccak256 hash of the underlying memory\n     */\n    function keccak(MemView memView) internal pure returns (bytes32 digest) {\n        uint256 loc_ = memView.loc();\n        uint256 len_ = memView.len();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            digest := keccak256(loc_, len_)\n        }\n    }\n\n    /**\n     * @notice Adds a salt to the keccak256 hash of the underlying data and returns the keccak256 hash of the\n     * resulting data.\n     * @param memView       The memory view\n     * @return digestSalted keccak256(salt, keccak256(memView))\n     */\n    function keccakSalted(MemView memView, bytes32 salt) internal pure returns (bytes32 digestSalted) {\n        return keccak256(bytes.concat(salt, memView.keccak()));\n    }\n\n    // ════════════════════════════════════════════ SLICING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Safe slicing without memory modification.\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the given index\n     */\n    function slice(MemView memView, uint256 index_, uint256 len_) internal pure returns (MemView) {\n        uint256 loc_ = memView.loc();\n        // Ensure it doesn't overrun the view\n        if (loc_ + index_ + len_ \u003e memView.end()) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // loc_ + index_ \u003c= memView.end()\n            return build({loc_: loc_ + index_, len_: len_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing bytes from `index` to end(memView).\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @return The new view for the slice starting from the given index until the initial view endpoint\n     */\n    function sliceFrom(MemView memView, uint256 index_) internal pure returns (MemView) {\n        uint256 len_ = memView.len();\n        // Ensure it doesn't overrun the view\n        if (index_ \u003e len_) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // index_ \u003c= len_ =\u003e memView.loc() + index_ \u003c= memView.loc() + memView.len() == memView.end()\n            return build({loc_: memView.loc() + index_, len_: len_ - index_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the first `len` bytes.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the initial view beginning\n     */\n    function prefix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        return memView.slice({index_: 0, len_: len_});\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the last `len` byte.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length until the initial view endpoint\n     */\n    function postfix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        uint256 viewLen = memView.len();\n        // Ensure it doesn't overrun the view\n        if (len_ \u003e viewLen) {\n            revert ViewOverrun();\n        }\n        // Could do the unchecked math due to the check above\n        uint256 index_;\n        unchecked {\n            index_ = viewLen - len_;\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // len_ \u003c= memView.len() =\u003e memView.loc() \u003c= loc_ \u003c= memView.end()\n            return build({loc_: memView.loc() + viewLen - len_, len_: len_});\n        }\n    }\n\n    // ═══════════════════════════════════════════ INDEXING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Load up to 32 bytes from the view onto the stack.\n     * @dev Returns a bytes32 with only the `bytes_` HIGHEST bytes set.\n     * This can be immediately cast to a smaller fixed-length byte array.\n     * To automatically cast to an integer, use `indexUint`.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return result       The 32 byte result having only `bytes_` highest bytes set\n     */\n    function index(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (bytes32 result) {\n        if (bytes_ == 0) {\n            return bytes32(0);\n        }\n        // Can't load more than 32 bytes to the stack in one go\n        if (bytes_ \u003e 32) {\n            revert IndexedTooMuch();\n        }\n        // The last indexed byte should be within view boundaries\n        if (index_ + bytes_ \u003e memView.len()) {\n            revert ViewOverrun();\n        }\n        uint256 bitLength = bytes_ \u003c\u003c 3; // bytes_ * 8\n        uint256 loc_ = memView.loc();\n        // Get a mask with `bitLength` highest bits set\n        uint256 mask;\n        // 0x800...00 binary representation is 100...00\n        // sar stands for \"signed arithmetic shift\": https://en.wikipedia.org/wiki/Arithmetic_shift\n        // sar(N-1, 100...00) = 11...100..00, with exactly N highest bits set to 1\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            mask := sar(sub(bitLength, 1), 0x8000000000000000000000000000000000000000000000000000000000000000)\n        }\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load a full word using index offset, and apply mask to ignore non-relevant bytes\n            result := and(mload(add(loc_, index_)), mask)\n        }\n    }\n\n    /**\n     * @notice Parse an unsigned integer from the view at `index`.\n     * @dev Requires that the view have \u003e= `bytes_` bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return The unsigned integer\n     */\n    function indexUint(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (uint256) {\n        bytes32 indexedBytes = memView.index(index_, bytes_);\n        // `index()` returns left-aligned `bytes_`, while integers are right-aligned\n        // Shifting here to right-align with the full 32 bytes word: need to shift right `(32 - bytes_)` bytes\n        unchecked {\n            // memView.index() reverts when bytes_ \u003e 32, thus unchecked math\n            return uint256(indexedBytes) \u003e\u003e ((32 - bytes_) \u003c\u003c 3);\n        }\n    }\n\n    /**\n     * @notice Parse an address from the view at `index`.\n     * @dev Requires that the view have \u003e= 20 bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @return The address\n     */\n    function indexAddress(MemView memView, uint256 index_) internal pure returns (address) {\n        // index 20 bytes as `uint160`, and then cast to `address`\n        return address(uint160(memView.indexUint(index_, 20)));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns a memory view over the specified memory location\n    /// without checking if it points to unallocated memory.\n    function _unsafeBuildUnchecked(uint256 loc_, uint256 len_) private pure returns (MemView) {\n        // There is no scenario where loc or len would overflow uint128, so we omit this check.\n        // We use the highest 128 bits to encode the location and the lowest 128 bits to encode the length.\n        return MemView.wrap((loc_ \u003c\u003c 128) | len_);\n    }\n\n    /**\n     * @notice Copy the view to a location, return an unsafe memory reference\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memView       The memory view\n     * @param newLoc        The new location to copy the underlying view data\n     * @return The memory view over the unsafe memory with the copied underlying data\n     */\n    function _unsafeCopyTo(MemView memView, uint256 newLoc) private view returns (MemView) {\n        uint256 len_ = memView.len();\n        uint256 oldLoc = memView.loc();\n\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (newLoc \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        bool res;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // use the identity precompile (0x04) to copy\n            res := staticcall(gas(), 0x04, oldLoc, len_, newLoc, len_)\n        }\n        if (!res) revert PrecompileOutOfGas();\n        return _unsafeBuildUnchecked({loc_: newLoc, len_: len_});\n    }\n\n    /**\n     * @notice Join the views in memory, return an unsafe reference to the memory.\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memViews      The memory views\n     * @return The conjoined view pointing to the new memory\n     */\n    function _unsafeJoin(MemView[] memory memViews, uint256 location) private view returns (MemView) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (location \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        // Copy the views to the specified location one by one, by tracking the amount of copied bytes so far\n        uint256 offset = 0;\n        for (uint256 i = 0; i \u003c memViews.length;) {\n            MemView memView = memViews[i];\n            // We can use the unchecked math here as location + sum(view.length) will never overflow uint256\n            unchecked {\n                _unsafeCopyTo(memView, location + offset);\n                offset += memView.len();\n                ++i;\n            }\n        }\n        return _unsafeBuildUnchecked({loc_: location, len_: offset});\n    }\n}\n\n// contracts/libs/merkle/MerkleMath.sol\n\nlibrary MerkleMath {\n    // ═════════════════════════════════════════ BASIC MERKLE CALCULATIONS ═════════════════════════════════════════════\n\n    /**\n     * @notice Calculates the merkle root for the given leaf and merkle proof.\n     * @dev Will revert if proof length exceeds the tree height.\n     * @param index     Index of `leaf` in tree\n     * @param leaf      Leaf of the merkle tree\n     * @param proof     Proof of inclusion of `leaf` in the tree\n     * @param height    Height of the merkle tree\n     * @return root_    Calculated Merkle Root\n     */\n    function proofRoot(uint256 index, bytes32 leaf, bytes32[] memory proof, uint256 height)\n        internal\n        pure\n        returns (bytes32 root_)\n    {\n        // Proof length could not exceed the tree height\n        uint256 proofLen = proof.length;\n        if (proofLen \u003e height) revert TreeHeightTooLow();\n        root_ = leaf;\n        /// @dev Apply unchecked to all ++h operations\n        unchecked {\n            // Go up the tree levels from the leaf following the proof\n            for (uint256 h = 0; h \u003c proofLen; ++h) {\n                // Get a sibling node on current level: this is proof[h]\n                root_ = getParent(root_, proof[h], index, h);\n            }\n            // Go up to the root: the remaining siblings are EMPTY\n            for (uint256 h = proofLen; h \u003c height; ++h) {\n                root_ = getParent(root_, bytes32(0), index, h);\n            }\n        }\n    }\n\n    /**\n     * @notice Calculates the parent of a node on the path from one of the leafs to root.\n     * @param node          Node on a path from tree leaf to root\n     * @param sibling       Sibling for a given node\n     * @param leafIndex     Index of the tree leaf\n     * @param nodeHeight    \"Level height\" for `node` (ZERO for leafs, ORIGIN_TREE_HEIGHT for root)\n     */\n    function getParent(bytes32 node, bytes32 sibling, uint256 leafIndex, uint256 nodeHeight)\n        internal\n        pure\n        returns (bytes32 parent)\n    {\n        // Index for `node` on its \"tree level\" is (leafIndex / 2**height)\n        // \"Left child\" has even index, \"right child\" has odd index\n        if ((leafIndex \u003e\u003e nodeHeight) \u0026 1 == 0) {\n            // Left child\n            return getParent(node, sibling);\n        } else {\n            // Right child\n            return getParent(sibling, node);\n        }\n    }\n\n    /// @notice Calculates the parent of tow nodes in the merkle tree.\n    /// @dev We use implementation with H(0,0) = 0\n    /// This makes EVERY empty node in the tree equal to ZERO,\n    /// saving us from storing H(0,0), H(H(0,0), H(0, 0)), and so on\n    /// @param leftChild    Left child of the calculated node\n    /// @param rightChild   Right child of the calculated node\n    /// @return parent      Value for the node having above mentioned children\n    function getParent(bytes32 leftChild, bytes32 rightChild) internal pure returns (bytes32 parent) {\n        if (leftChild == bytes32(0) \u0026\u0026 rightChild == bytes32(0)) {\n            return 0;\n        } else {\n            return keccak256(bytes.concat(leftChild, rightChild));\n        }\n    }\n\n    // ════════════════════════════════ ROOT/PROOF CALCULATION FOR A LIST OF LEAFS ═════════════════════════════════════\n\n    /**\n     * @notice Calculates merkle root for a list of given leafs.\n     * Merkle Tree is constructed by padding the list with ZERO values for leafs until list length is `2**height`.\n     * Merkle Root is calculated for the constructed tree, and then saved in `leafs[0]`.\n     * \u003e Note:\n     * \u003e - `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * \u003e - Caller is expected not to reuse `hashes` list after the call, and only use `leafs[0]` value,\n     * which is guaranteed to contain the calculated merkle root.\n     * \u003e - root is calculated using the `H(0,0) = 0` Merkle Tree implementation. See MerkleTree.sol for details.\n     * @dev Amount of leaves should be at most `2**height`\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param height    Height of the Merkle Tree to construct\n     */\n    function calculateRoot(bytes32[] memory hashes, uint256 height) internal pure {\n        uint256 levelLength = hashes.length;\n        // Amount of hashes could not exceed amount of leafs in tree with the given height\n        if (levelLength \u003e (1 \u003c\u003c height)) revert TreeHeightTooLow();\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\": the amount of iterations for the for loop above.\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n            }\n        }\n    }\n\n    /**\n     * @notice Generates a proof of inclusion of a leaf in the list. If the requested index is outside\n     * of the list range, generates a proof of inclusion for an empty leaf (proof of non-inclusion).\n     * The Merkle Tree is constructed by padding the list with ZERO values until list length is a power of two\n     * __AND__ index is in the extended list range. For example:\n     *  - `hashes.length == 6` and `0 \u003c= index \u003c= 7` will \"extend\" the list to 8 entries.\n     *  - `hashes.length == 6` and `7 \u003c index \u003c= 15` will \"extend\" the list to 16 entries.\n     * \u003e Note: `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * Caller is expected not to reuse `hashes` list after the call.\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param index     Leaf index to generate the proof for\n     * @return proof    Generated merkle proof\n     */\n    function calculateProof(bytes32[] memory hashes, uint256 index) internal pure returns (bytes32[] memory proof) {\n        // Use only meaningful values for the shortened proof\n        // Check if index is within the list range (we want to generates proofs for outside leafs as well)\n        uint256 height = getHeight(index \u003c hashes.length ? hashes.length : (index + 1));\n        proof = new bytes32[](height);\n        uint256 levelLength = hashes.length;\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Use sibling for the merkle proof; `index^1` is index of our sibling\n                proof[h] = (index ^ 1 \u003c levelLength) ? hashes[index ^ 1] : bytes32(0);\n\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\"\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n                // Traverse to parent node\n                index \u003e\u003e= 1;\n            }\n        }\n    }\n\n    /// @notice Returns the height of the tree having a given amount of leafs.\n    function getHeight(uint256 leafs) internal pure returns (uint256 height) {\n        uint256 amount = 1;\n        while (amount \u003c leafs) {\n            unchecked {\n                ++height;\n            }\n            amount \u003c\u003c= 1;\n        }\n    }\n}\n\n// contracts/libs/stack/GasData.sol\n\n/// GasData in encoded data with \"basic information about gas prices\" for some chain.\ntype GasData is uint96;\n\nusing GasDataLib for GasData global;\n\n/// ChainGas is encoded data with given chain's \"basic information about gas prices\".\ntype ChainGas is uint128;\n\nusing GasDataLib for ChainGas global;\n\n/// Library for encoding and decoding GasData and ChainGas structs.\n/// # GasData\n/// `GasData` is a struct to store the \"basic information about gas prices\", that could\n/// be later used to approximate the cost of a message execution, and thus derive the\n/// minimal tip values for sending a message to the chain.\n/// \u003e - `GasData` is supposed to be cached by `GasOracle` contract, allowing to store the\n/// \u003e approximates instead of the exact values, and thus save on storage costs.\n/// \u003e - For instance, if `GasOracle` only updates the values on +- 10% change, having an\n/// \u003e 0.4% error on the approximates would be acceptable.\n/// `GasData` is supposed to be included in the Origin's state, which are synced across\n/// chains using Agent-signed snapshots and attestations.\n/// ## GasData stack layout (from highest bits to lowest)\n///\n/// | Position   | Field        | Type   | Bytes | Description                                         |\n/// | ---------- | ------------ | ------ | ----- | --------------------------------------------------- |\n/// | (012..010] | gasPrice     | uint16 | 2     | Gas price for the chain (in Wei per gas unit)       |\n/// | (010..008] | dataPrice    | uint16 | 2     | Calldata price (in Wei per byte of content)         |\n/// | (008..006] | execBuffer   | uint16 | 2     | Tx fee safety buffer for message execution (in Wei) |\n/// | (006..004] | amortAttCost | uint16 | 2     | Amortized cost for attestation submission (in Wei)  |\n/// | (004..002] | etherPrice   | uint16 | 2     | Chain's Ether Price / Mainnet Ether Price (in BWAD) |\n/// | (002..000] | markup       | uint16 | 2     | Markup for the message execution (in BWAD)          |\n/// \u003e See Number.sol for more details on `Number` type and BWAD (binary WAD) math.\n///\n/// ## ChainGas stack layout (from highest bits to lowest)\n///\n/// | Position   | Field   | Type   | Bytes | Description      |\n/// | ---------- | ------- | ------ | ----- | ---------------- |\n/// | (016..004] | gasData | uint96 | 12    | Chain's gas data |\n/// | (004..000] | domain  | uint32 | 4     | Chain's domain   |\nlibrary GasDataLib {\n    /// @dev Amount of bits to shift to gasPrice field\n    uint96 private constant SHIFT_GAS_PRICE = 10 * 8;\n    /// @dev Amount of bits to shift to dataPrice field\n    uint96 private constant SHIFT_DATA_PRICE = 8 * 8;\n    /// @dev Amount of bits to shift to execBuffer field\n    uint96 private constant SHIFT_EXEC_BUFFER = 6 * 8;\n    /// @dev Amount of bits to shift to amortAttCost field\n    uint96 private constant SHIFT_AMORT_ATT_COST = 4 * 8;\n    /// @dev Amount of bits to shift to etherPrice field\n    uint96 private constant SHIFT_ETHER_PRICE = 2 * 8;\n\n    /// @dev Amount of bits to shift to gasData field\n    uint128 private constant SHIFT_GAS_DATA = 4 * 8;\n\n    // ═════════════════════════════════════════════════ GAS DATA ══════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded GasData struct with the given fields.\n    /// @param gasPrice_        Gas price for the chain (in Wei per gas unit)\n    /// @param dataPrice_       Calldata price (in Wei per byte of content)\n    /// @param execBuffer_      Tx fee safety buffer for message execution (in Wei)\n    /// @param amortAttCost_    Amortized cost for attestation submission (in Wei)\n    /// @param etherPrice_      Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n    /// @param markup_          Markup for the message execution (in BWAD)\n    function encodeGasData(\n        Number gasPrice_,\n        Number dataPrice_,\n        Number execBuffer_,\n        Number amortAttCost_,\n        Number etherPrice_,\n        Number markup_\n    ) internal pure returns (GasData) {\n        // Number type wraps uint16, so could safely be casted to uint96\n        // forgefmt: disable-next-item\n        return GasData.wrap(\n            uint96(Number.unwrap(gasPrice_)) \u003c\u003c SHIFT_GAS_PRICE |\n            uint96(Number.unwrap(dataPrice_)) \u003c\u003c SHIFT_DATA_PRICE |\n            uint96(Number.unwrap(execBuffer_)) \u003c\u003c SHIFT_EXEC_BUFFER |\n            uint96(Number.unwrap(amortAttCost_)) \u003c\u003c SHIFT_AMORT_ATT_COST |\n            uint96(Number.unwrap(etherPrice_)) \u003c\u003c SHIFT_ETHER_PRICE |\n            uint96(Number.unwrap(markup_))\n        );\n    }\n\n    /// @notice Wraps padded uint256 value into GasData struct.\n    function wrapGasData(uint256 paddedGasData) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(paddedGasData));\n    }\n\n    /// @notice Returns the gas price, in Wei per gas unit.\n    function gasPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_GAS_PRICE));\n    }\n\n    /// @notice Returns the calldata price, in Wei per byte of content.\n    function dataPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_DATA_PRICE));\n    }\n\n    /// @notice Returns the tx fee safety buffer for message execution, in Wei.\n    function execBuffer(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_EXEC_BUFFER));\n    }\n\n    /// @notice Returns the amortized cost for attestation submission, in Wei.\n    function amortAttCost(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_AMORT_ATT_COST));\n    }\n\n    /// @notice Returns the ratio of Chain's Ether Price / Mainnet Ether Price, in BWAD math.\n    function etherPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_ETHER_PRICE));\n    }\n\n    /// @notice Returns the markup for the message execution, in BWAD math.\n    function markup(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data)));\n    }\n\n    // ════════════════════════════════════════════════ CHAIN DATA ═════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded ChainGas struct with the given fields.\n    /// @param gasData_ Chain's gas data\n    /// @param domain_  Chain's domain\n    function encodeChainGas(GasData gasData_, uint32 domain_) internal pure returns (ChainGas) {\n        // GasData type wraps uint96, so could safely be casted to uint128\n        return ChainGas.wrap(uint128(GasData.unwrap(gasData_)) \u003c\u003c SHIFT_GAS_DATA | uint128(domain_));\n    }\n\n    /// @notice Wraps padded uint256 value into ChainGas struct.\n    function wrapChainGas(uint256 paddedChainGas) internal pure returns (ChainGas) {\n        // Casting to uint128 will truncate the highest bits, which is the behavior we want\n        return ChainGas.wrap(uint128(paddedChainGas));\n    }\n\n    /// @notice Returns the chain's gas data.\n    function gasData(ChainGas data) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(ChainGas.unwrap(data) \u003e\u003e SHIFT_GAS_DATA));\n    }\n\n    /// @notice Returns the chain's domain.\n    function domain(ChainGas data) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(ChainGas.unwrap(data));\n    }\n\n    /// @notice Returns the hash for the list of ChainGas structs.\n    function snapGasHash(ChainGas[] memory snapGas) internal pure returns (bytes32 snapGasHash_) {\n        // Use assembly to calculate the hash of the array without copying it\n        // ChainGas takes a single word of storage, thus ChainGas[] is stored in the following way:\n        // 0x00: length of the array, in words\n        // 0x20: first ChainGas struct\n        // 0x40: second ChainGas struct\n        // And so on...\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Find the location where the array data starts, we add 0x20 to skip the length field\n            let loc := add(snapGas, 0x20)\n            // Load the length of the array (in words).\n            // Shifting left 5 bits is equivalent to multiplying by 32: this converts from words to bytes.\n            let len := shl(5, mload(snapGas))\n            // Calculate the hash of the array\n            snapGasHash_ := keccak256(loc, len)\n        }\n    }\n}\n\n// contracts/libs/stack/Header.sol\n\n/// Header is encoded data with \"general routing information\".\ntype Header is uint136;\n\nusing HeaderLib for Header global;\n\n/// Types of messages supported by Origin-Destination\n/// - Base: message sent by protocol user, contains tips\n/// - Manager: message sent between AgentManager contracts located on different chains, no tips\nenum MessageFlag {\n    Base,\n    Manager\n}\n\nusing HeaderLib for MessageFlag global;\n\n/// Library for formatting _the header part_ of _the messages used by Origin and Destination_.\n/// - Header represents general information for routing a Message for Origin and Destination.\n/// - Header occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n///\n/// # Header stack layout (from highest bits to lowest)\n///\n/// | Position   | Field            | Type   | Bytes | Description                             |\n/// | ---------- | ---------------- | ------ | ----- | --------------------------------------- |\n/// | (017..016] | flag             | uint8  | 1     | Flag specifying the type of message     |\n/// | (016..012] | origin           | uint32 | 4     | Domain where message originated         |\n/// | (012..008] | nonce            | uint32 | 4     | Message nonce on the origin domain      |\n/// | (008..004] | destination      | uint32 | 4     | Domain where message will be executed   |\n/// | (004..000] | optimisticPeriod | uint32 | 4     | Optimistic period that will be enforced |\nlibrary HeaderLib {\n    /// @dev Amount of bits to shift to flag field\n    uint136 private constant SHIFT_FLAG = 16 * 8;\n    /// @dev Amount of bits to shift to origin field\n    uint136 private constant SHIFT_ORIGIN = 12 * 8;\n    /// @dev Amount of bits to shift to nonce field\n    uint136 private constant SHIFT_NONCE = 8 * 8;\n    /// @dev Amount of bits to shift to destination field\n    uint136 private constant SHIFT_DESTINATION = 4 * 8;\n\n    /// @notice Returns an encoded header with provided fields\n    /// @param origin_              Domain of origin chain\n    /// @param nonce_               Message nonce on origin chain\n    /// @param destination_         Domain of destination chain\n    /// @param optimisticPeriod_    Optimistic period for message execution\n    function encodeHeader(\n        MessageFlag flag_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint32 destination_,\n        uint32 optimisticPeriod_\n    ) internal pure returns (Header) {\n        // All casts below are upcasts, so they are safe\n        // forgefmt: disable-next-item\n        return Header.wrap(\n            uint136(uint8(flag_)) \u003c\u003c SHIFT_FLAG |\n            uint136(origin_) \u003c\u003c SHIFT_ORIGIN |\n            uint136(nonce_) \u003c\u003c SHIFT_NONCE |\n            uint136(destination_) \u003c\u003c SHIFT_DESTINATION |\n            uint136(optimisticPeriod_)\n        );\n    }\n\n    /// @notice Checks that the header is a valid encoded header.\n    function isHeader(uint256 paddedHeader) internal pure returns (bool) {\n        // Check that flag is within range\n        return _flag(paddedHeader) \u003c= uint8(type(MessageFlag).max);\n    }\n\n    /// @notice Wraps the padded encoded request into a Header-typed value.\n    /// @dev The \"padded\" header is simply an encoded header casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded headers\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedHeader) internal pure returns (Header) {\n        // Check that flag is within range\n        if (!isHeader(paddedHeader)) revert FlagOutOfRange();\n        // Casting to uint136 will truncate the highest bits, which is the behavior we want\n        return Header.wrap(uint136(paddedHeader));\n    }\n\n    /// @notice Returns header's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Header header) internal pure returns (bytes32 hashedHeader) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store header in scratch space\n            mstore(0, header)\n            // Compute hash of header padded to 32 bytes\n            hashedHeader := keccak256(0, 32)\n        }\n    }\n\n    // ══════════════════════════════════════════════ HEADER SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns header's flag field\n    function flag(Header header) internal pure returns (MessageFlag) {\n        // We check that flag is within range when wrapping the header, so this cast is safe\n        return MessageFlag(_flag(Header.unwrap(header)));\n    }\n\n    /// @notice Returns header's origin field\n    function origin(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_ORIGIN);\n    }\n\n    /// @notice Returns header's nonce field\n    function nonce(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_NONCE);\n    }\n\n    /// @notice Returns header's destination field\n    function destination(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_DESTINATION);\n    }\n\n    /// @notice Returns header's optimistic seconds field\n    function optimisticPeriod(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns header's flag field without casting to MessageFlag\n    function _flag(uint256 paddedHeader) private pure returns (uint8) {\n        // Casting to uint8 will truncate the highest bits, which is the behavior we want\n        return uint8(paddedHeader \u003e\u003e SHIFT_FLAG);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n     * constructor.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall \u0026\u0026 _initialized \u003c 1) || (!AddressUpgradeable.isContract(address(this)) \u0026\u0026 _initialized == 1),\n            \"Initializable: contract is already initialized\"\n        );\n        _initialized = 1;\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: setting the version to 255 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing \u0026\u0026 _initialized \u003c version, \"Initializable: contract is already initialized\");\n        _initialized = version;\n        _initializing = true;\n        _;\n        _initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        require(_initializing, \"Initializable: contract is not initializing\");\n        _;\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized != type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint8) {\n        return _initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _initializing;\n    }\n}\n\n// contracts/interfaces/IAgentManager.sol\n\ninterface IAgentManager {\n    /**\n     * @notice Allows Inbox to open a Dispute between a Guard and a Notary, if they are both not in Dispute already.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Guard or Notary is already in Dispute.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Allows Inbox to slash an agent, if their fraud was proven.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Domain doesn't match the saved agent domain.\n     * @param domain    Domain where the Agent is active\n     * @param agent     Address of the Agent\n     * @param prover    Address that initially provided fraud proof\n     */\n    function slashAgent(uint32 domain, address agent, address prover) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest known root of the Agent Merkle Tree.\n     */\n    function agentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns the number of opened Disputes.\n     * @dev This includes the Disputes that have been resolved already.\n     */\n    function getDisputesAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns information about the dispute with the given index.\n     * @dev Will revert if dispute with given index hasn't been opened yet.\n     * @param index             Dispute index\n     * @return guard            Address of the Guard in the Dispute\n     * @return notary           Address of the Notary in the Dispute\n     * @return slashedAgent     Address of the Agent who was slashed when Dispute was resolved\n     * @return fraudProver      Address who provided fraud proof to resolve the Dispute\n     * @return reportPayload    Raw payload with report data that led to the Dispute\n     * @return reportSignature  Guard signature for the report payload\n     */\n    function getDispute(uint256 index)\n        external\n        view\n        returns (\n            address guard,\n            address notary,\n            address slashedAgent,\n            address fraudProver,\n            bytes memory reportPayload,\n            bytes memory reportSignature\n        );\n\n    /**\n     * @notice Returns the current Dispute status of a given agent. See Structures.sol for details.\n     * @dev Every returned value will be set to zero if agent was not slashed and is not in Dispute.\n     * `rival` and `disputePtr` will be set to zero if the agent was slashed without being in Dispute.\n     * @param agent         Agent address\n     * @return flag         Flag describing the current Dispute status for the agent: None/Pending/Slashed\n     * @return rival        Address of the rival agent in the Dispute\n     * @return fraudProver  Address who provided fraud proof to resolve the Dispute\n     * @return disputePtr   Index of the opened Dispute PLUS ONE. Zero if agent is not in Dispute.\n     */\n    function disputeStatus(address agent)\n        external\n        view\n        returns (DisputeFlag flag, address rival, address fraudProver, uint256 disputePtr);\n}\n\n// contracts/interfaces/IAgentSecured.sol\n\ninterface IAgentSecured {\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * between a Guard and a Notary has been opened.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * has been resolved due to one of the agents being slashed.\n     * \u003e `rivalIndex` will be ZERO, if the slashed agent was not in the Dispute.\n     * @param slashedIndex  Index of the slashed agent in the Agent Merkle Tree\n     * @param rivalIndex    Index of the their Dispute Rival in the Agent Merkle Tree\n     */\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the address of the local AgentManager contract, which is treated as\n     * the \"source of truth\" for agent statuses.\n     */\n    function agentManager() external view returns (address);\n\n    /**\n     * @notice Returns the address of the local Inbox contract, which is treated as\n     * the \"source of truth\" for agent-signed statements.\n     * @dev Inbox passes verified agent statements to `IAgentSecured` contract.\n     */\n    function inbox() external view returns (address);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns (flag, openedAt, resolvedAt) that describes the latest status of\n     * the latest dispute for an agent with a given index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param agentIndex    Agent index in the Agent Merkle Tree\n     * @return              Latest dispute status for the given agent: (flag, openedAt, resolvedAt)\n     */\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory);\n}\n\n// contracts/libs/memory/ByteString.sol\n\n/// @dev CallData is a memory view over the payload to be used for an external call, i.e.\n/// recipient.call(callData). Its length is always (4 + 32 * N) bytes:\n/// - First 4 bytes represent the function selector.\n/// - 32 * N bytes represent N words that function arguments occupy.\ntype CallData is uint256;\n\n/// @dev Attach library functions to CallData\nusing ByteString for CallData global;\n\n/// @dev Signature is a memory view over a \"65 bytes\" array representing a ECDSA signature.\ntype Signature is uint256;\n\n/// @dev Attach library functions to Signature\nusing ByteString for Signature global;\n\nlibrary ByteString {\n    using MemViewLib for bytes;\n\n    /**\n     * @dev non-compact ECDSA signatures are enforced as of OZ 4.7.3\n     *\n     *      Signature payload memory layout\n     * [000 .. 032) r   bytes32 32 bytes\n     * [032 .. 064) s   bytes32 32 bytes\n     * [064 .. 065) v   uint8    1 byte\n     */\n    uint256 internal constant SIGNATURE_LENGTH = 65;\n    uint256 private constant OFFSET_R = 0;\n    uint256 private constant OFFSET_S = 32;\n    uint256 private constant OFFSET_V = 64;\n\n    /**\n     * @dev Calldata memory layout\n     * [000 .. 004) selector    bytes4  4 bytes\n     *      Optional: N function arguments\n     * [004 .. 036) arg1        bytes32 32 bytes\n     *      ..\n     * [AAA .. END) argN        bytes32 32 bytes\n     */\n    uint256 internal constant SELECTOR_LENGTH = 4;\n    uint256 private constant OFFSET_SELECTOR = 0;\n    uint256 private constant OFFSET_ARGUMENTS = SELECTOR_LENGTH;\n\n    // ═════════════════════════════════════════════════ SIGNATURE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the signature payload from the given values.\n     * @dev Using ByteString.formatSignature({r: r, s: s, v: v}) will make sure\n     * that params are given in the right order.\n     */\n    function formatSignature(bytes32 r, bytes32 s, uint8 v) internal pure returns (bytes memory) {\n        return abi.encodePacked(r, s, v);\n    }\n\n    /**\n     * @notice Returns a Signature view over for the given payload.\n     * @dev Will revert if the payload is not a signature.\n     */\n    function castToSignature(bytes memory payload) internal pure returns (Signature) {\n        return castToSignature(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Signature view.\n     * @dev Will revert if the memory view is not over a signature.\n     */\n    function castToSignature(MemView memView) internal pure returns (Signature) {\n        if (!isSignature(memView)) revert UnformattedSignature();\n        return Signature.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a signature\n     */\n    function isSignature(MemView memView) internal pure returns (bool) {\n        return memView.len() == SIGNATURE_LENGTH;\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Signature signature) internal pure returns (MemView) {\n        return MemView.wrap(Signature.unwrap(signature));\n    }\n\n    // ═════════════════════════════════════════════ SIGNATURE SLICING ═════════════════════════════════════════════════\n\n    /// @notice Unpacks signature payload into (r, s, v) parameters.\n    /// @dev Make sure to verify signature length with isSignature() beforehand.\n    function toRSV(Signature signature) internal pure returns (bytes32 r, bytes32 s, uint8 v) {\n        // Get the underlying memory view\n        MemView memView = unwrap(signature);\n        r = memView.index({index_: OFFSET_R, bytes_: 32});\n        s = memView.index({index_: OFFSET_S, bytes_: 32});\n        // Can be safely casted to uint8, since we index a single byte\n        v = uint8(memView.indexUint({index_: OFFSET_V, bytes_: 1}));\n    }\n\n    // ═════════════════════════════════════════════════ CALLDATA ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the calldata with the modified arguments:\n     * the existing arguments are prepended with the arguments from the prefix.\n     * @dev Given:\n     *  - `calldata = abi.encodeWithSelector(foo.selector, d, e);`\n     *  - `prefix = abi.encode(a, b, c);`\n     *  - `a`, `b`, `c` are arguments of static type (i.e. not dynamically sized ones)\n     *      Then:\n     *  - Function will return abi.encodeWithSelector(foo.selector, a, c, c, d, e)\n     *  - Returned calldata will trigger `foo(a, b, c, d, e)` when used for a contract call.\n     * Note: for clarification as to what types are considered static, see\n     * https://docs.soliditylang.org/en/latest/abi-spec.html#formal-specification-of-the-encoding\n     * @param callData  Calldata that needs to be modified\n     * @param prefix    ABI-encoded arguments to use as the first arguments in the new calldata\n     * @return Modified calldata having prefix as the first arguments.\n     */\n    function addPrefix(CallData callData, bytes memory prefix) internal view returns (bytes memory) {\n        // Prefix should occupy a whole amount of words in memory\n        if (!_fullWords(prefix.length)) revert UnformattedCallDataPrefix();\n        MemView[] memory views = new MemView[](3);\n        // Use payload's function selector\n        views[0] = abi.encodePacked(callData.callSelector()).ref();\n        // Use prefix as the first arguments\n        views[1] = prefix.ref();\n        // Use payload's remaining arguments\n        views[2] = callData.arguments();\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a CallData view over for the given payload.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(bytes memory payload) internal pure returns (CallData) {\n        return castToCallData(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a CallData view.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(MemView memView) internal pure returns (CallData) {\n        if (!isCallData(memView)) revert UnformattedCallData();\n        return CallData.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a valid calldata, i.e.\n     * a function selector, followed by arbitrary amount of arguments.\n     */\n    function isCallData(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Calldata should at least have a function selector\n        if (length \u003c SELECTOR_LENGTH) return false;\n        // The remainder of the calldata should be exactly N memory words (N \u003e= 0)\n        return _fullWords(length - SELECTOR_LENGTH);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(CallData callData) internal pure returns (MemView) {\n        return MemView.wrap(CallData.unwrap(callData));\n    }\n\n    /// @notice Returns callData's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(CallData callData) internal pure returns (bytes32) {\n        return callData.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ CALLDATA SLICING ══════════════════════════════════════════════════\n\n    /**\n     * @notice Returns amount of memory words (32 byte chunks) the function arguments\n     * occupy in the calldata.\n     * @dev This might differ from amount of arguments supplied, if any of the arguments\n     * occupies more than one memory slot. It is true, however, that argument part of the payload\n     * occupies exactly N words, even for dynamic types like `bytes`\n     */\n    function argumentWords(CallData callData) internal pure returns (uint256) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        // Equivalent of (length - SELECTOR_LENGTH) / 32\n        return (memView.len() - SELECTOR_LENGTH) \u003e\u003e 5;\n    }\n\n    /// @notice Returns selector for the provided calldata.\n    function callSelector(CallData callData) internal pure returns (bytes4) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return bytes4(memView.index({index_: OFFSET_SELECTOR, bytes_: SELECTOR_LENGTH}));\n    }\n\n    /// @notice Returns abi encoded arguments for the provided calldata.\n    function arguments(CallData callData) internal pure returns (MemView) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return memView.sliceFrom({index_: OFFSET_ARGUMENTS});\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if length is full amount of memory words (32 bytes).\n    function _fullWords(uint256 length) internal pure returns (bool) {\n        // The equivalent of length % 32 == 0\n        return length \u0026 31 == 0;\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n    function __Context_init() internal onlyInitializing {\n    }\n\n    function __Context_init_unchained() internal onlyInitializing {\n    }\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[50] private __gap;\n}\n\n// contracts/libs/merkle/MerkleTree.sol\n\n/// `BaseTree` is a struct representing incremental merkle tree.\n/// - Contains only the current branch.\n/// - The number of inserted leaves is stored externally, and is later supplied for tree operations.\n/// - Has a fixed height of `ORIGIN_TREE_HEIGHT`.\n/// - Can store up to `2 ** ORIGIN_TREE_HEIGHT - 1` leaves.\n/// \u003e Note: the hash function for the tree `H(x, y)` is defined as:\n/// \u003e - `H(0,0) = 0`\n/// \u003e - `H(x,y) = keccak256(x, y), when (x != 0 || y != 0)`\n/// ## Invariant for leafs\n/// - The leftmost empty leaf has `index == count`, where `count` is the amount of the inserted leafs so far.\n/// - Value for any empty leaf or node is bytes32(0).\n/// ## Invariant for current branch\n/// `branch[i]` is always the value of a node on the i-th level.\n/// Levels are numbered from leafs to root: `0 .. ORIGIN_TREE_HEIGHT`.\n/// `branch[i]` stores the value for the node, such that:\n//  - The node is a \"left child\" (e.g. has an even index).\n/// - The node must have two non-empty children.\n/// - Out of all level's \"left child\" nodes with \"non-empty children\",\n/// the one with the biggest index (the rightmost one) is stored as `branch[i]`.\n/// \u003e __`branch` could be used to form a proof of inclusion for the first empty leaf (`index == count`).__\n/// _Here is how:_\n/// - Let's walk along the path from the \"first empty leaf\" to the root.\n/// - i-th bit of the \"first empty leaf\" index (which is equal to `count`) determines if the path's node\n/// for this i-th level is a \"left child\" or a \"right child\".\n/// - i-th bit in `count` is 0 → we are the left child on this level → sibling is the right child\n/// that does not exist yet → `proof[i] = bytes32(0)`.\n/// - i-th bit in `count` is 1 → we are the right child on this level → sibling is the left child\n/// sibling is the rightmost \"left child\" node on the level → `proof[i] = branch[i]`.\n/// \u003e Therefore `proof[i] = (count \u0026 (1 \u003c\u003c i)) == 0 ? bytes32(0) : branch[i])`\nstruct BaseTree {\n    bytes32[ORIGIN_TREE_HEIGHT] branch;\n}\n\nusing MerkleTree for BaseTree global;\n\n/// `HistoricalTree` is an incremental merkle tree keeping track of its historical merkle roots.\n/// \u003e - `roots[N]` is the root of the tree after `N` leafs were inserted\n/// \u003e - `roots[0] == bytes32(0)`\n/// @param tree     Incremental merkle tree\n/// @param roots    Historical merkle roots of the tree\nstruct HistoricalTree {\n    BaseTree tree;\n    bytes32[] roots;\n}\n\nusing MerkleTree for HistoricalTree global;\n\n/// `DynamicTree` is a struct representing a Merkle Tree with `2**AGENT_TREE_HEIGHT` leaves.\n/// - A single operation is available: update value for leaf with an arbitrary index (which might be a non-empty leaf).\n/// - This is done by requesting the proof of inclusion for the old value, which is used to both\n/// verify the old value, and calculate the new root.\n/// \u003e Based on Original idea from [ER forum post](https://ethresear.ch/t/efficient-on-chain-dynamic-merkle-tree/11054).\nstruct DynamicTree {\n    bytes32 root;\n}\n\nusing MerkleTree for DynamicTree global;\n\n/// MerkleTree is work based on Nomad's Merkle.sol, which is used under MIT OR Apache-2.0\n/// [link](https://github.com/nomad-xyz/monorepo/blob/main/packages/contracts-core/contracts/libs/Merkle.sol).\n/// With the following changes:\n/// - Adapted for Solidity 0.8.x.\n/// - Amount of tree leaves stored externally.\n/// - Added thorough documentation.\n/// - `H(0,0) = 0` optimization from [ER forum post](https://ethresear.ch/t/optimizing-sparse-merkle-trees/3751/6).\n/// \u003e Nomad's Merkle.sol is work based on eth2 deposit contract, which is used under CC0-1.0\n///[link](https://github.com/ethereum/deposit_contract/blob/dev/deposit_contract/contracts/validator_registration.v.py).\n/// With the following changes:\n/// \u003e - Implemented in Solidity 0.7.6 (eth2 deposit contract implemented in Vyper).\n/// \u003e - `H() = keccak256()` is used as the hashing function instead of `sha256()`.\nlibrary MerkleTree {\n    /// @dev For root calculation we need at least one empty leaf, thus the minus one in the formula.\n    uint256 internal constant MAX_LEAVES = 2 ** ORIGIN_TREE_HEIGHT - 1;\n\n    // ═════════════════════════════════════════════════ BASE TREE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Inserts `node` into merkle tree\n     * @dev Reverts if tree is full\n     * @param newCount  Amount of inserted leaves in the tree after the insertion (i.e. current + 1)\n     * @param node      Element to insert into tree\n     */\n    function insertBase(BaseTree storage tree, uint256 newCount, bytes32 node) internal {\n        if (newCount \u003e MAX_LEAVES) revert MerkleTreeFull();\n        // We go up the tree following the branch from the empty leaf AFTER the just inserted one.\n        // We stop when we find the first \"right child\" node.\n        // Its sibling is now the rightmost \"left child\" node that has two non-empty children.\n        // Therefore we need to update `tree.branch` value on this level.\n        // One could see that `tree.branch` value on lower and higher levels remain unchanged.\n\n        // Loop invariant: `node` is the current level's value for the branch from JUST INSERTED leaf\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            if ((newCount \u0026 1) == 1) {\n                // Found the first \"right child\" node on the branch from EMPTY leaf\n                // `node` is the value for node on branch from JUST INSERTED leaf\n                // Which in this case is the \"left child\".\n                // We update tree.branch and exit\n                tree.branch[i] = node;\n                return;\n            }\n            // On the branch from EMPTY leaf this is still a \"left child\".\n            // Meaning on branch from JUST INSERTED leaf, `node` is a right child.\n            // We compute value for `node` parent using `tree.branch` invariant:\n            // This is the rightmost \"left child\" node, which would be sibling of `node`.\n            node = MerkleMath.getParent(tree.branch[i], node);\n            // Get the parent index, and go to the next tree level\n            newCount \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n        // As the loop should always end prematurely with the `return` statement,\n        // this code should be unreachable. We assert `false` just to be safe.\n        assert(false);\n    }\n\n    /**\n     * @notice Calculates and returns current root of the merkle tree.\n     * @param count     Current amount of inserted leaves in the tree\n     * @return current  Calculated root of `tree`\n     */\n    function rootBase(BaseTree storage tree, uint256 count) internal view returns (bytes32 current) {\n        // To calculate the root we follow the branch of first EMPTY leaf (index == count)\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            // Check if we are the left or the right child on the current level\n            if ((count \u0026 1) == 1) {\n                // We are the right child. Our sibling is the \"rightmost\" \"left-child\" node\n                // that has two non-empty children → sibling is `tree.branch[i]`\n                current = MerkleMath.getParent(tree.branch[i], current);\n            } else {\n                // We are the left child. Our sibling does not exist yet → sibling is EMPTY\n                current = MerkleMath.getParent(current, bytes32(0));\n            }\n            // Get the parent index, and go to the next tree level\n            count \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    // ══════════════════════════════════════════════ HISTORICAL TREE ══════════════════════════════════════════════════\n\n    /// @notice Initializes the historical roots for the tree by inserting an empty root.\n    // solhint-disable-next-line ordering\n    function initializeRoots(HistoricalTree storage tree) internal returns (bytes32 savedRoot) {\n        // This should only be called once, when the contract is initialized\n        assert(tree.roots.length == 0);\n        // Save root for empty merkle tree: bytes32(0)\n        tree.roots.push(savedRoot);\n    }\n\n    /// @notice Inserts a new leaf into the merkle tree.\n    /// @dev Reverts if tree is full.\n    /// @param node         Element to insert into tree\n    /// @return newRoot     Merkle root after the leaf was inserted\n    function insert(HistoricalTree storage tree, bytes32 node) internal returns (bytes32 newRoot) {\n        // Tree count after the new leaf will be inserted (we store roots[0] as root of empty tree)\n        uint256 newCount = tree.roots.length;\n        tree.tree.insertBase(newCount, node);\n        // Save the new root\n        newRoot = tree.tree.rootBase(newCount);\n        tree.roots.push(newRoot);\n    }\n\n    /// @notice Returns the historical root of the merkle tree.\n    /// @dev Reverts if not enough leafs have been inserted.\n    /// @param count            Amount of leafs in the tree at some point of time\n    /// @return historicalRoot  Merkle root after `count` leafs were inserted\n    function root(HistoricalTree storage tree, uint256 count) internal view returns (bytes32 historicalRoot) {\n        if (count \u003e= tree.roots.length) revert NotEnoughLeafs();\n        return tree.roots[count];\n    }\n\n    // ═══════════════════════════════════════════════ DYNAMIC TREE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Updates the value for the leaf with the given index in the Dynamic Merkle Tree.\n     * @dev Will revert if incorrect proof of inclusion for old value is supplied.\n     * @param tree          Dynamic merkle tree\n     * @param index         Index of the leaf to update\n     * @param oldValue      Previous value of the leaf\n     * @param branch        Proof of inclusion of previous value into the tree\n     * @param newValue      New leaf value to assign\n     * @return newRoot      New value for the Merkle Root after the leaf is updated\n     */\n    function update(\n        DynamicTree storage tree,\n        uint256 index,\n        bytes32 oldValue,\n        bytes32[] memory branch,\n        bytes32 newValue\n    ) internal returns (bytes32 newRoot) {\n        // Check that the old value + proof result in a correct root\n        if (MerkleMath.proofRoot(index, oldValue, branch, AGENT_TREE_HEIGHT) != tree.root) {\n            revert LeafNotProven();\n        }\n        // New root is new value + the same proof (values for sibling nodes are not updated)\n        newRoot = MerkleMath.proofRoot(index, newValue, branch, AGENT_TREE_HEIGHT);\n        // Write the new root\n        tree.root = newRoot;\n    }\n}\n\n// contracts/libs/stack/Tips.sol\n\n/// Tips is encoded data with \"tips paid for sending a base message\".\n/// Note: even though uint256 is also an underlying type for MemView, Tips is stored ON STACK.\ntype Tips is uint256;\n\nusing TipsLib for Tips global;\n\n/// # Tips\n/// Library for formatting _the tips part_ of _the base messages_.\n///\n/// ## How the tips are awarded\n/// Tips are paid for sending a base message, and are split across all the agents that\n/// made the message execution on destination chain possible.\n/// ### Summit tips\n/// Split between:\n///     - Guard posting a snapshot with state ST_G for the origin chain.\n///     - Notary posting a snapshot SN_N using ST_G. This creates attestation A.\n///     - Notary posting a message receipt after it is executed on destination chain.\n/// ### Attestation tips\n/// Paid to:\n///     - Notary posting attestation A to destination chain.\n/// ### Execution tips\n/// Paid to:\n///     - First executor performing a valid execution attempt (correct proofs, optimistic period over),\n///      using attestation A to prove message inclusion on origin chain, whether the recipient reverted or not.\n/// ### Delivery tips.\n/// Paid to:\n///     - Executor who successfully executed the message on destination chain.\n///\n/// ## Tips encoding\n/// - Tips occupy a single storage word, and thus are stored on stack instead of being stored in memory.\n/// - The actual tip values should be determined by multiplying stored values by divided by TIPS_MULTIPLIER=2**32.\n/// - Tips are packed into a single word of storage, while allowing real values up to ~8*10**28 for every tip category.\n/// \u003e The only downside is that the \"real tip values\" are now multiplies of ~4*10**9, which should be fine even for\n/// the chains with the most expensive gas currency.\n/// # Tips stack layout (from highest bits to lowest)\n///\n/// | Position   | Field          | Type   | Bytes | Description                                                |\n/// | ---------- | -------------- | ------ | ----- | ---------------------------------------------------------- |\n/// | (032..024] | summitTip      | uint64 | 8     | Tip for agents interacting with Summit contract            |\n/// | (024..016] | attestationTip | uint64 | 8     | Tip for Notary posting attestation to Destination contract |\n/// | (016..008] | executionTip   | uint64 | 8     | Tip for valid execution attempt on destination chain       |\n/// | (008..000] | deliveryTip    | uint64 | 8     | Tip for successful message delivery on destination chain   |\n\nlibrary TipsLib {\n    using SafeCast for uint256;\n\n    /// @dev Amount of bits to shift to summitTip field\n    uint256 private constant SHIFT_SUMMIT_TIP = 24 * 8;\n    /// @dev Amount of bits to shift to attestationTip field\n    uint256 private constant SHIFT_ATTESTATION_TIP = 16 * 8;\n    /// @dev Amount of bits to shift to executionTip field\n    uint256 private constant SHIFT_EXECUTION_TIP = 8 * 8;\n\n    // ═══════════════════════════════════════════════════ TIPS ════════════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips with the given fields\n    /// @param summitTip_        Tip for agents interacting with Summit contract, divided by TIPS_MULTIPLIER\n    /// @param attestationTip_   Tip for Notary posting attestation to Destination contract, divided by TIPS_MULTIPLIER\n    /// @param executionTip_     Tip for valid execution attempt on destination chain, divided by TIPS_MULTIPLIER\n    /// @param deliveryTip_      Tip for successful message delivery on destination chain, divided by TIPS_MULTIPLIER\n    function encodeTips(uint64 summitTip_, uint64 attestationTip_, uint64 executionTip_, uint64 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // forgefmt: disable-next-item\n        return Tips.wrap(\n            uint256(summitTip_) \u003c\u003c SHIFT_SUMMIT_TIP |\n            uint256(attestationTip_) \u003c\u003c SHIFT_ATTESTATION_TIP |\n            uint256(executionTip_) \u003c\u003c SHIFT_EXECUTION_TIP |\n            uint256(deliveryTip_)\n        );\n    }\n\n    /// @notice Convenience function to encode tips with uint256 values.\n    function encodeTips256(uint256 summitTip_, uint256 attestationTip_, uint256 executionTip_, uint256 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // In practice, the tips amounts are not supposed to be higher than 2**96, and with 32 bits of granularity\n        // using uint64 is enough to store the values. However, we still check for overflow just in case.\n        // TODO: consider using Number type to store the tips values.\n        return encodeTips({\n            summitTip_: (summitTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            attestationTip_: (attestationTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            executionTip_: (executionTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            deliveryTip_: (deliveryTip_ \u003e\u003e TIPS_GRANULARITY).toUint64()\n        });\n    }\n\n    /// @notice Wraps the padded encoded tips into a Tips-typed value.\n    /// @dev There is no actual padding here, as the underlying type is already uint256,\n    /// but we include this function for consistency and to be future-proof, if tips will eventually use anything\n    /// smaller than uint256.\n    function wrapPadded(uint256 paddedTips) internal pure returns (Tips) {\n        return Tips.wrap(paddedTips);\n    }\n\n    /**\n     * @notice Returns a formatted Tips payload specifying empty tips.\n     * @return Formatted tips\n     */\n    function emptyTips() internal pure returns (Tips) {\n        return Tips.wrap(0);\n    }\n\n    /// @notice Returns tips's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Tips tips) internal pure returns (bytes32 hashedTips) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store tips in scratch space\n            mstore(0, tips)\n            // Compute hash of tips padded to 32 bytes\n            hashedTips := keccak256(0, 32)\n        }\n    }\n\n    // ═══════════════════════════════════════════════ TIPS SLICING ════════════════════════════════════════════════════\n\n    /// @notice Returns summitTip field\n    function summitTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_SUMMIT_TIP);\n    }\n\n    /// @notice Returns attestationTip field\n    function attestationTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_ATTESTATION_TIP);\n    }\n\n    /// @notice Returns executionTip field\n    function executionTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_EXECUTION_TIP);\n    }\n\n    /// @notice Returns deliveryTip field\n    function deliveryTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips));\n    }\n\n    // ════════════════════════════════════════════════ TIPS VALUE ═════════════════════════════════════════════════════\n\n    /// @notice Returns total value of the tips payload.\n    /// This is the sum of the encoded values, scaled up by TIPS_MULTIPLIER\n    function value(Tips tips) internal pure returns (uint256 value_) {\n        value_ = uint256(tips.summitTip()) + tips.attestationTip() + tips.executionTip() + tips.deliveryTip();\n        value_ \u003c\u003c= TIPS_GRANULARITY;\n    }\n\n    /// @notice Increases the delivery tip to match the new value.\n    function matchValue(Tips tips, uint256 newValue) internal pure returns (Tips newTips) {\n        uint256 oldValue = tips.value();\n        if (newValue \u003c oldValue) revert TipsValueTooLow();\n        // We want to increase the delivery tip, while keeping the other tips the same\n        unchecked {\n            uint256 delta = (newValue - oldValue) \u003e\u003e TIPS_GRANULARITY;\n            // `delta` fits into uint224, as TIPS_GRANULARITY is 32, so this never overflows uint256.\n            // In practice, this will never overflow uint64 as well, but we still check it just in case.\n            if (delta + tips.deliveryTip() \u003e type(uint64).max) revert TipsOverflow();\n            // Delivery tips occupy lowest 8 bytes, so we can just add delta to the tips value\n            // to effectively increase the delivery tip (knowing that delta fits into uint64).\n            newTips = Tips.wrap(Tips.unwrap(tips) + delta);\n        }\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    function __Ownable_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable_init_unchained() internal onlyInitializing {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n    function __Ownable2Step_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable2Step_init_unchained() internal onlyInitializing {\n    }\n    address private _pendingOwner;\n\n    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Returns the address of the pending owner.\n     */\n    function pendingOwner() public view virtual returns (address) {\n        return _pendingOwner;\n    }\n\n    /**\n     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual override onlyOwner {\n        _pendingOwner = newOwner;\n        emit OwnershipTransferStarted(owner(), newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual override {\n        delete _pendingOwner;\n        super._transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev The new owner accepts the ownership transfer.\n     */\n    function acceptOwnership() public virtual {\n        address sender = _msgSender();\n        require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n        _transferOwnership(sender);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// contracts/libs/memory/State.sol\n\n/// State is a memory view over a formatted state payload.\ntype State is uint256;\n\nusing StateLib for State global;\n\n/// # State\n/// State structure represents the state of Origin contract at some point of time.\n/// - State is structured in a way to track the updates of the Origin Merkle Tree.\n/// - State includes root of the Origin Merkle Tree, origin domain and some additional metadata.\n/// ## Origin Merkle Tree\n/// Hash of every sent message is inserted in the Origin Merkle Tree, which changes\n/// the value of Origin Merkle Root (which is the root for the mentioned tree).\n/// - Origin has a single Merkle Tree for all messages, regardless of their destination domain.\n/// - This leads to Origin state being updated if and only if a message was sent in a block.\n/// - Origin contract is a \"source of truth\" for states: a state is considered \"valid\" in its Origin,\n/// if it matches the state of the Origin contract after the N-th (nonce) message was sent.\n///\n/// # Memory layout of State fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                    |\n/// | ---------- | ----------- | ------- | ----- | ------------------------------ |\n/// | [000..032) | root        | bytes32 | 32    | Root of the Origin Merkle Tree |\n/// | [032..036) | origin      | uint32  | 4     | Domain where Origin is located |\n/// | [036..040) | nonce       | uint32  | 4     | Amount of sent messages        |\n/// | [040..045) | blockNumber | uint40  | 5     | Block of last sent message     |\n/// | [045..050) | timestamp   | uint40  | 5     | Time of last sent message      |\n/// | [050..062) | gasData     | uint96  | 12    | Gas data for the chain         |\n///\n/// @dev State could be used to form a Snapshot to be signed by a Guard or a Notary.\nlibrary StateLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_ROOT = 0;\n    uint256 private constant OFFSET_ORIGIN = 32;\n    uint256 private constant OFFSET_NONCE = 36;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 40;\n    uint256 private constant OFFSET_TIMESTAMP = 45;\n    uint256 private constant OFFSET_GAS_DATA = 50;\n\n    // ═══════════════════════════════════════════════════ STATE ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted State payload with provided fields\n     * @param root_         New merkle root\n     * @param origin_       Domain of Origin's chain\n     * @param nonce_        Nonce of the merkle root\n     * @param blockNumber_  Block number when root was saved in Origin\n     * @param timestamp_    Block timestamp when root was saved in Origin\n     * @param gasData_      Gas data for the chain\n     * @return Formatted state\n     */\n    function formatState(\n        bytes32 root_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_,\n        GasData gasData_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(root_, origin_, nonce_, blockNumber_, timestamp_, gasData_);\n    }\n\n    /**\n     * @notice Returns a State view over the given payload.\n     * @dev Will revert if the payload is not a state.\n     */\n    function castToState(bytes memory payload) internal pure returns (State) {\n        return castToState(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a State view.\n     * @dev Will revert if the memory view is not over a state.\n     */\n    function castToState(MemView memView) internal pure returns (State) {\n        if (!isState(memView)) revert UnformattedState();\n        return State.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted State.\n    function isState(MemView memView) internal pure returns (bool) {\n        return memView.len() == STATE_LENGTH;\n    }\n\n    /// @notice Returns the hash of a State, that could be later signed by a Guard to signal\n    /// that the state is invalid.\n    function hashInvalid(State state) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(stateInvalidSalt, keccak(state))\n        return state.unwrap().keccakSalted(STATE_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(State state) internal pure returns (MemView) {\n        return MemView.wrap(State.unwrap(state));\n    }\n\n    /// @notice Compares two State structures.\n    function equals(State a, State b) internal pure returns (bool) {\n        // Length of a State payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═══════════════════════════════════════════════ STATE HASHING ═══════════════════════════════════════════════════\n\n    /// @notice Returns the hash of the State.\n    /// @dev We are using the Merkle Root of a tree with two leafs (see below) as state hash.\n    function leaf(State state) internal pure returns (bytes32) {\n        (bytes32 leftLeaf_, bytes32 rightLeaf_) = state.subLeafs();\n        // Final hash is the parent of these leafs\n        return keccak256(bytes.concat(leftLeaf_, rightLeaf_));\n    }\n\n    /// @notice Returns \"sub-leafs\" of the State. Hash of these \"sub leafs\" is going to be used\n    /// as a \"state leaf\" in the \"Snapshot Merkle Tree\".\n    /// This enables proving that leftLeaf = (root, origin) was a part of the \"Snapshot Merkle Tree\",\n    /// by combining `rightLeaf` with the remainder of the \"Snapshot Merkle Proof\".\n    function subLeafs(State state) internal pure returns (bytes32 leftLeaf_, bytes32 rightLeaf_) {\n        MemView memView = state.unwrap();\n        // Left leaf is (root, origin)\n        leftLeaf_ = memView.prefix({len_: OFFSET_NONCE}).keccak();\n        // Right leaf is (metadata), or (nonce, blockNumber, timestamp)\n        rightLeaf_ = memView.sliceFrom({index_: OFFSET_NONCE}).keccak();\n    }\n\n    /// @notice Returns the left \"sub-leaf\" of the State.\n    function leftLeaf(bytes32 root_, uint32 origin_) internal pure returns (bytes32) {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(root_, origin_));\n    }\n\n    /// @notice Returns the right \"sub-leaf\" of the State.\n    function rightLeaf(uint32 nonce_, uint40 blockNumber_, uint40 timestamp_, GasData gasData_)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(nonce_, blockNumber_, timestamp_, gasData_));\n    }\n\n    // ═══════════════════════════════════════════════ STATE SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns a historical Merkle root from the Origin contract.\n    function root(State state) internal pure returns (bytes32) {\n        return state.unwrap().index({index_: OFFSET_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns domain of chain where the Origin contract is deployed.\n    function origin(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns nonce of Origin contract at the time, when `root` was the Merkle root.\n    function nonce(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when `root` was saved in Origin.\n    function blockNumber(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when `root` was saved in Origin.\n    /// @dev This is the timestamp according to the origin chain.\n    function timestamp(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n\n    /// @notice Returns gas data for the chain.\n    function gasData(State state) internal pure returns (GasData) {\n        return GasDataLib.wrapGasData(state.unwrap().indexUint({index_: OFFSET_GAS_DATA, bytes_: GAS_DATA_LENGTH}));\n    }\n}\n\n// contracts/libs/memory/BaseMessage.sol\n\n/// BaseMessage is a memory view over the base message supported by Origin-Destination\ntype BaseMessage is uint256;\n\nusing BaseMessageLib for BaseMessage global;\n\n/// BaseMessage structure represents a base message sent via the Origin-Destination contracts.\n/// - It only contains data relevant to the base message, the rest of data is encoded in the message header.\n/// - `sender` and `recipient` for EVM chains are EVM addresses casted to bytes32, while preserving left-alignment.\n/// - `tips` and `request` parameters are specified by a message sender\n/// \u003e Origin will calculate minimum tips for given request and content length, and will reject messages with tips\n/// lower than that.\n///\n/// # Memory layout of BaseMessage fields\n///\n/// | Position   | Field     | Type    | Bytes | Description                            |\n/// | ---------- | --------- | ------- | ----- | -------------------------------------- |\n/// | [000..032) | tips      | uint256 | 32    | Encoded tips paid on origin chain      |\n/// | [032..064) | sender    | bytes32 | 32    | Sender address on origin chain         |\n/// | [064..096) | recipient | bytes32 | 32    | Recipient address on destination chain |\n/// | [096..116) | request   | uint160 | 20    | Encoded request for message execution  |\n/// | [104..AAA) | content   | bytes   | ??    | Content to be passed to recipient      |\nlibrary BaseMessageLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_TIPS = 0;\n    uint256 private constant OFFSET_SENDER = 32;\n    uint256 private constant OFFSET_RECIPIENT = 64;\n    uint256 private constant OFFSET_REQUEST = OFFSET_RECIPIENT + TIPS_LENGTH;\n    uint256 private constant OFFSET_CONTENT = OFFSET_REQUEST + REQUEST_LENGTH;\n\n    // ═══════════════════════════════════════════════ BASE MESSAGE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted BaseMessage payload with provided fields.\n     * @param tips_         Encoded tips information\n     * @param sender_       Sender address on origin chain\n     * @param recipient_    Recipient address on destination chain\n     * @param request_      Encoded request for message execution\n     * @param content_      Raw content to be passed to recipient on destination chain\n     * @return Formatted base message\n     */\n    function formatBaseMessage(Tips tips_, bytes32 sender_, bytes32 recipient_, Request request_, bytes memory content_)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return abi.encodePacked(tips_, sender_, recipient_, request_, content_);\n    }\n\n    /**\n     * @notice Returns a BaseMessage view over the given payload.\n     * @dev Will revert if the payload is not a base message.\n     */\n    function castToBaseMessage(bytes memory payload) internal pure returns (BaseMessage) {\n        return castToBaseMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a BaseMessage view.\n     * @dev Will revert if the memory view is not over a base message payload.\n     */\n    function castToBaseMessage(MemView memView) internal pure returns (BaseMessage) {\n        if (!isBaseMessage(memView)) revert UnformattedBaseMessage();\n        return BaseMessage.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted BaseMessage.\n    function isBaseMessage(MemView memView) internal pure returns (bool) {\n        // Check if sender, recipient, tips fields exist\n        return (memView.len() \u003e= OFFSET_CONTENT);\n        // Content could be empty, so we don't check that\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(BaseMessage baseMessage) internal pure returns (MemView) {\n        return MemView.wrap(BaseMessage.unwrap(baseMessage));\n    }\n\n    /// @notice Returns baseMessage's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        // We hash \"tips\" and \"everything but tips\" to make tips proofs easier to verify\n        return MerkleMath.getParent(baseMessage.tips().leaf(), baseMessage.bodyLeaf());\n    }\n\n    /// @notice Returns hash for the \"everything but tips\" part of the base message.\n    function bodyLeaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_SENDER}).keccak();\n    }\n\n    // ═══════════════════════════════════════════ BASE MESSAGE SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips paid on origin chain.\n    function tips(BaseMessage baseMessage) internal pure returns (Tips) {\n        return TipsLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_TIPS, bytes_: TIPS_LENGTH})));\n    }\n\n    /// @notice Returns sender address on origin chain.\n    function sender(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_SENDER, bytes_: 32});\n    }\n\n    /// @notice Returns recipient address on destination chain.\n    function recipient(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_RECIPIENT, bytes_: 32});\n    }\n\n    /// @notice Returns an encoded request for message execution on destination chain.\n    function request(BaseMessage baseMessage) internal pure returns (Request) {\n        return RequestLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_REQUEST, bytes_: REQUEST_LENGTH})));\n    }\n\n    /// @notice Returns an untyped memory view over the content to be passed to recipient.\n    function content(BaseMessage baseMessage) internal pure returns (MemView) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_CONTENT});\n    }\n}\n\n// contracts/base/MessagingBase.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for all messaging contracts.\n * - Provides context on the local chain's domain.\n * - Provides ownership functionality.\n * - Will be providing pausing functionality when it is implemented.\n */\nabstract contract MessagingBase is MultiCallable, Versioned, Ownable2StepUpgradeable {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @notice Domain of the local chain, set once upon contract creation\n    uint32 public immutable localDomain;\n    // @notice Domain of the Synapse chain, set once upon contract creation\n    uint32 public immutable synapseDomain;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev gap for upgrade safety\n    uint256[50] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    constructor(string memory version_, uint32 synapseDomain_) Versioned(version_) {\n        localDomain = ChainContext.chainId();\n        synapseDomain = synapseDomain_;\n    }\n\n    // TODO: Implement pausing\n\n    /**\n     * @dev Should be impossible to renounce ownership;\n     * we override OpenZeppelin OwnableUpgradeable's\n     * implementation of renounceOwnership to make it a no-op\n     */\n    function renounceOwnership() public override onlyOwner {} //solhint-disable-line no-empty-blocks\n}\n\n// contracts/libs/memory/Message.sol\n\n/// Message is a memory over over a formatted message payload.\ntype Message is uint256;\n\nusing MessageLib for Message global;\n\n/// Library for formatting the various messages supported by Origin and Destination.\n///\n/// # Message memory layout\n///\n/// | Position   | Field  | Type    | Bytes | Description                                             |\n/// | ---------- | ------ | ------- | ----- | ------------------------------------------------------- |\n/// | [000..017) | header | uint136 | 17    | Encoded general routing information for the message     |\n/// | [017..AAA) | body   | bytes   | ??    | Formatted payload (according to flag) with message body |\nlibrary MessageLib {\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MemViewLib for bytes;\n    using HeaderLib for MemView;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_HEADER = 0;\n    uint256 private constant OFFSET_BODY = OFFSET_HEADER + HEADER_LENGTH;\n\n    // ══════════════════════════════════════════════════ MESSAGE ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns formatted message with provided fields.\n     * @param header_   Encoded general routing information for the message\n     * @param body_     Formatted payload (according to flag) with message body\n     * @return Formatted message\n     */\n    function formatMessage(Header header_, bytes memory body_) internal pure returns (bytes memory) {\n        return abi.encodePacked(header_, body_);\n    }\n\n    /**\n     * @notice Returns a Message view over for the given payload.\n     * @dev Will revert if the payload is not a message payload.\n     */\n    function castToMessage(bytes memory payload) internal pure returns (Message) {\n        return castToMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Message view.\n     * @dev Will revert if the memory view is not over a message payload.\n     */\n    function castToMessage(MemView memView) internal pure returns (Message) {\n        if (!isMessage(memView)) revert UnformattedMessage();\n        return Message.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Message.\n     */\n    function isMessage(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Check if headers exist in the payload\n        if (length \u003c OFFSET_BODY) return false;\n        // Check that Header is valid\n        uint256 paddedHeader = _header(memView);\n        if (!HeaderLib.isHeader(paddedHeader)) return false;\n        // Check that body is formatted according to the flag\n        // Only Base/Manager message flags exist\n        if (HeaderLib.wrapPadded(paddedHeader).flag() == MessageFlag.Base) {\n            // Check if body is a formatted base message\n            return _body(memView).isBaseMessage();\n        } else {\n            // Check if body is a formatted calldata for AgentManager call\n            return _body(memView).isCallData();\n        }\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Message message) internal pure returns (MemView) {\n        return MemView.wrap(Message.unwrap(message));\n    }\n\n    /// @notice Returns message's hash: a leaf to be inserted in the Merkle tree.\n    function leaf(Message message) internal pure returns (bytes32) {\n        // We hash header and body separately to make message proofs easier to verify\n        Header header_ = message.header();\n        // Only Base/Manager message flags exist\n        if (header_.flag() == MessageFlag.Base) {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToBaseMessage().leaf());\n        } else {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToCallData().leaf());\n        }\n    }\n\n    // ══════════════════════════════════════════════ MESSAGE SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns message's encoded header field.\n    function header(Message message) internal pure returns (Header) {\n        return HeaderLib.wrapPadded((message.unwrap().indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH})));\n    }\n\n    /// @notice Returns message's body field as an untyped memory view.\n    function body(Message message) internal pure returns (MemView) {\n        MemView memView = message.unwrap();\n        return _body(memView);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns message's padded header without checking that it is a valid header.\n    function _header(MemView memView) private pure returns (uint256) {\n        return memView.indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH});\n    }\n\n    /// @dev Returns an untyped memory view over the body field without checking\n    /// if the whole payload or the body are properly formatted.\n    function _body(MemView memView) private pure returns (MemView) {\n        return memView.sliceFrom({index_: OFFSET_BODY});\n    }\n}\n\n// contracts/base/AgentSecured.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for messaging contracts that are secured by the agent manager.\n * `AgentSecured` relies on `AgentManager` to provide the following functionality:\n * - Keep track of agents and their statuses.\n * - Pass agent-signed statements that were verified by the agent manager.\n * - These statements are considered valid indefinitely, unless the agent is disputed.\n * - Disputes are opened and resolved by the agent manager.\n * \u003e `AgentSecured` implementation should never use statements signed by agents that are disputed.\n */\nabstract contract AgentSecured is MessagingBase, IAgentSecured {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    address public immutable agentManager;\n\n    /// @inheritdoc IAgentSecured\n    address public immutable inbox;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    // (agent index =\u003e their dispute status: flag, openedAt, resolvedAt)\n    mapping(uint32 =\u003e DisputeStatus) internal _disputes;\n\n    /// @dev gap for upgrade safety\n    uint256[49] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    modifier onlyAgentManager() {\n        if (msg.sender != agentManager) revert CallerNotAgentManager();\n        _;\n    }\n\n    modifier onlyInbox() {\n        if (msg.sender != inbox) revert CallerNotInbox();\n        _;\n    }\n\n    constructor(string memory version_, uint32 synapseDomain_, address agentManager_, address inbox_)\n        MessagingBase(version_, synapseDomain_)\n    {\n        agentManager = agentManager_;\n        inbox = inbox_;\n    }\n\n    // ════════════════════════════════════════════ ONLY AGENT MANAGER ═════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external onlyAgentManager {\n        uint40 openedAt = ChainContext.blockTimestamp();\n        DisputeStatus memory status = DisputeStatus({flag: DisputeFlag.Pending, openedAt: openedAt, resolvedAt: 0});\n        _disputes[guardIndex] = status;\n        _disputes[notaryIndex] = status;\n    }\n\n    /// @inheritdoc IAgentSecured\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external onlyAgentManager {\n        // Update the dispute status of the slashed agent first.\n        uint40 resolvedAt = ChainContext.blockTimestamp();\n        _disputes[slashedIndex].flag = DisputeFlag.Slashed;\n        _disputes[slashedIndex].resolvedAt = resolvedAt;\n        // Mark the rival agent as not disputed, if there was an ongoing dispute.\n        if (rivalIndex != 0) {\n            _disputes[rivalIndex].flag = DisputeFlag.None;\n            _disputes[rivalIndex].resolvedAt = resolvedAt;\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function agentStatus(address agent) external view returns (AgentStatus memory) {\n        return _agentStatus(agent);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status) {\n        return _getAgent(index);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory) {\n        return _disputes[agentIndex];\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns status of the given agent: (flag, domain, index).\n    function _agentStatus(address agent) internal view returns (AgentStatus memory) {\n        return IAgentManager(agentManager).agentStatus(agent);\n    }\n\n    /// @dev Returns agent and their status for a given agent index. Returns zero values for non existing indexes.\n    function _getAgent(uint256 index) internal view returns (address agent, AgentStatus memory status) {\n        return IAgentManager(agentManager).getAgent(index);\n    }\n\n    /// @dev Checks if a Dispute exists for the given Notary. This function returns true, if\n    /// Notary is in ongoing Dispute, or if Dispute was resolved not in Notary's favor.\n    /// In both cases we can't trust Notary's data.\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeExists(uint32 notaryIndex) internal view returns (bool) {\n        return _disputes[notaryIndex].flag != DisputeFlag.None;\n    }\n\n    /// @dev Checks if a Notary recently won a Dispute and is still in the \"post-dispute\" timeout period.\n    /// In this period we still can't trust Notary's data, though we can optimistically assume that\n    /// that the data will be correct after the timeout (assuming no new Disputes are opened).\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeTimeout(uint32 notaryIndex) internal view returns (bool) {\n        DisputeStatus memory status = _disputes[notaryIndex];\n        // Exit early if Notary is in ongoing Dispute / slashed.\n        if (status.flag != DisputeFlag.None) return false;\n        // Check if Notary has been in any Dispute at all.\n        if (status.openedAt == 0) return false;\n        // Otherwise check if the Dispute timeout is still active.\n        return block.timestamp \u003c status.resolvedAt + DISPUTE_TIMEOUT_NOTARY;\n    }\n}\n\n// contracts/hubs/StateHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StateHub` is a parent contract for `Origin`. It is responsible for the following:\n/// - Keeping track of the historical Origin Merkle Tree containing all the message hashes.\n/// - Keeping track of the historical Origin States, as well as verifying their validity.\nabstract contract StateHub is AgentSecured, StateHubEvents, IStateHub {\n    using SafeCast for uint256;\n    using StateLib for bytes;\n\n    struct OriginState {\n        uint40 blockNumber;\n        uint40 timestamp;\n        GasData gasData;\n    }\n    // Bits left for tight packing: 80\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Historical Merkle Tree\n    /// Note: Takes two storage slots\n    HistoricalTree private _tree;\n\n    /// @dev All historical contract States\n    OriginState[] private _originStates;\n\n    /// @dev gap for upgrade safety\n    uint256[47] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IStateHub\n    function isValidState(bytes memory statePayload) external view returns (bool isValid) {\n        // This will revert if payload is not a formatted state\n        State state = statePayload.castToState();\n        return _isValidState(state);\n    }\n\n    /// @inheritdoc IStateHub\n    function statesAmount() external view returns (uint256) {\n        return _originStates.length;\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestLatestState() external view returns (bytes memory stateData) {\n        // This never underflows, assuming the contract was initialized\n        return suggestState(_nextNonce() - 1);\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestState(uint32 nonce) public view returns (bytes memory stateData) {\n        // This will revert if nonce is out of range\n        bytes32 root = _tree.root(nonce);\n        return _formatOriginState(_originStates[nonce], root, localDomain, nonce);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Initializes the saved states list by inserting a state for an empty Merkle Tree.\n    function _initializeStates() internal {\n        // This should only be called once, when the contract is initialized\n        // This will revert if _tree.roots is non-empty\n        bytes32 savedRoot = _tree.initializeRoots();\n        // Save root for empty merkle _tree with block number and timestamp of initialization\n        _saveState(savedRoot, _toOriginState());\n    }\n\n    /// @dev Inserts leaf into the Merkle Tree and saves the updated origin State.\n    function _insertAndSave(bytes32 leaf) internal {\n        bytes32 newRoot = _tree.insert(leaf);\n        _saveState(newRoot, _toOriginState());\n    }\n\n    /// @dev Saves an updated state of the Origin contract\n    function _saveState(bytes32 root, OriginState memory state) internal {\n        uint32 nonce = _nextNonce();\n        _originStates.push(state);\n        // Emit event with raw state data\n        emit StateSaved(_formatOriginState(state, root, localDomain, nonce));\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns nonce of the next sent message: the amount of saved States so far.\n    /// This always equals to \"total amount of sent messages\" plus 1.\n    function _nextNonce() internal view returns (uint32) {\n        // TODO: consider using more than 32 bits for origin nonces\n        return _originStates.length.toUint32();\n    }\n\n    /// @dev Checks if a state is valid, i.e. if it matches the historical one.\n    /// Reverts, if state refers to another Origin contract.\n    function _isValidState(State state) internal view returns (bool) {\n        // Check if state refers to this contract\n        if (state.origin() != localDomain) revert IncorrectOriginDomain();\n        // Check if nonce exists\n        uint32 nonce = state.nonce();\n        if (nonce \u003e= _originStates.length) return false;\n        // Check if state root matches the historical one\n        if (state.root() != _tree.root(nonce)) return false;\n        // Check if state metadata matches the historical one\n        return _areEqual(state, _originStates[nonce]);\n    }\n\n    // ═════════════════════════════════════════════ STRUCT FORMATTING ═════════════════════════════════════════════════\n\n    /// @dev Returns a formatted payload for a stored OriginState.\n    function _formatOriginState(OriginState memory originState, bytes32 root, uint32 origin, uint32 nonce)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return StateLib.formatState({\n            root_: root,\n            origin_: origin,\n            nonce_: nonce,\n            blockNumber_: originState.blockNumber,\n            timestamp_: originState.timestamp,\n            gasData_: originState.gasData\n        });\n    }\n\n    /// @dev Child contract should implement the logic for getting the current gas data from the gas oracle\n    /// to be saved as part of the Origin State.\n    // solhint-disable-next-line ordering\n    function _fetchGasData() internal view virtual returns (GasData);\n\n    /// @dev Returns a OriginState struct to save in the contract.\n    function _toOriginState() internal view returns (OriginState memory originState) {\n        originState.blockNumber = ChainContext.blockNumber();\n        originState.timestamp = ChainContext.blockTimestamp();\n        originState.gasData = _fetchGasData();\n    }\n\n    /// @dev Checks that a state and its Origin representation are equal.\n    function _areEqual(State state, OriginState memory originState) internal pure returns (bool) {\n        return state.blockNumber() == originState.blockNumber \u0026\u0026 state.timestamp() == originState.timestamp;\n    }\n}\n\n// contracts/Origin.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Origin` contract is used for sending messages to remote chains. It is done\n/// by inserting the message hashes into the Origin Merkle, which makes it possible to\n/// prove that message was sent using the Merkle proof against the Origin Merkle Root. This essentially\n/// compresses the list of messages into a single 32-byte value that needs to be stored on the destination chain.\n/// `Origin` is responsible for the following:\n/// - Formatting the sent message payloads, and inserting their hashes into the Origin Merkle Tree.\n/// - Keeping track of its own historical states (see parent contract `StateHub`).\n/// - Enforcing minimum tip values for sent base messages based on the provided execution requests.\n/// - Distributing the collected tips upon request from a local `AgentManager` contract.\ncontract Origin is StateHub, OriginEvents, InterfaceOrigin {\n    using MemViewLib for bytes;\n    using MessageLib for bytes;\n    using TipsLib for bytes;\n    using TypeCasts for address;\n\n    address public immutable gasOracle;\n\n    modifier onlyRemoteDestination(uint32 destination) {\n        if (destination == localDomain) revert IncorrectDestinationDomain();\n        _;\n    }\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_, address gasOracle_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {\n        gasOracle = gasOracle_;\n    }\n\n    /// @notice Initializes Origin contract:\n    /// - msg.sender is set as contract owner\n    /// - State of \"empty merkle tree\" is saved\n    function initialize() external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize \"states\": state of an \"empty merkle tree\" is saved\n        _initializeStates();\n    }\n\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable onlyRemoteDestination(destination) returns (uint32 messageNonce, bytes32 messageHash) {\n        // Check that content is not too large\n        if (content.length \u003e MAX_CONTENT_BYTES) revert ContentLengthTooBig();\n        // This will revert if msg.value is lower than value of minimum tips\n        Tips tips = _getMinimumTips(destination, paddedRequest, content.length).matchValue(msg.value);\n        Request request = RequestLib.wrapPadded(paddedRequest);\n        // Format the BaseMessage body\n        bytes memory body = BaseMessageLib.formatBaseMessage({\n            sender_: msg.sender.addressToBytes32(),\n            recipient_: recipient,\n            tips_: tips,\n            request_: request,\n            content_: content\n        });\n        // Send the message\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Base, body);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        onlyAgentManager\n        onlyRemoteDestination(destination)\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // AgentManager (checked via modifier) is responsible for constructing the calldata payload correctly.\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Manager, payload);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function withdrawTips(address recipient, uint256 amount) external onlyAgentManager {\n        if (address(this).balance \u003c amount) revert InsufficientEthBalance();\n        (bool success,) = recipient.call{value: amount}(\"\");\n        if (!success) revert EthTransferFailed();\n        emit TipWithdrawalCompleted(recipient, amount);\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue)\n    {\n        return _getMinimumTips(destination, paddedRequest, contentLength).value();\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Sends the given message to the specified destination. Message hash is inserted\n    /// into the Origin Merkle Tree, which will enable message execution on destination chain.\n    function _sendMessage(uint32 destination, uint32 optimisticPeriod, MessageFlag flag, bytes memory body)\n        internal\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // Format the message header\n        messageNonce = _nextNonce();\n        Header header = flag.encodeHeader({\n            origin_: localDomain,\n            nonce_: messageNonce,\n            destination_: destination,\n            optimisticPeriod_: optimisticPeriod\n        });\n        // Format the full message payload\n        bytes memory msgPayload = MessageLib.formatMessage(header, body);\n        // Insert new leaf into the Origin Merkle Tree and save the updated state\n        messageHash = msgPayload.castToMessage().leaf();\n        _insertAndSave(messageHash);\n        // Emit event with message information\n        emit Sent(messageHash, messageNonce, destination, msgPayload);\n        // Update the gas oracle data. We do this after the provided tips are checked so that\n        // the provided message is sent in the event that the gas oracle data is updated to a higher value.\n        InterfaceGasOracle(gasOracle).updateGasData(destination);\n        // TODO: consider doing this before the message is sent, while adjusting GasOracle.getMinimumTips() to\n        // use the pending gas oracle data.\n    }\n\n    /// @dev Returns the minimum tips for sending a message to the given destination with the given request and content.\n    function _getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        internal\n        view\n        returns (Tips)\n    {\n        return\n            TipsLib.wrapPadded(InterfaceGasOracle(gasOracle).getMinimumTips(destination, paddedRequest, contentLength));\n    }\n\n    /// @dev Gets the current gas data from the gas oracle to be saved as part of the Origin State.\n    function _fetchGasData() internal view override returns (GasData) {\n        return GasDataLib.wrapGasData(InterfaceGasOracle(gasOracle).getGasData());\n    }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"63475:9180:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;63475:9180:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"63475:9180:0:-:0;;;;;;;;","abiDefinition":[],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"Collection of functions related to the address type","kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"details\":\"Collection of functions related to the address type\",\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Origin.sol\":\"AddressUpgradeable\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Origin.sol\":{\"keccak256\":\"0x96775924f147f3d1f8df8cdf56731fe52a15af8d8e12e608efb8158c112b18cd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e642a27f5fab3c62b4c02e9754e9e42b1cf2e5381dbea9d3d106d23b7772ebe6\",\"dweb:/ipfs/QmUwn7ZyBvPkjnMuK8ZMSexBUdNQnVtxwyoAyT4DXLQjra\"]}},\"version\":1}"},"hashes":{}},"solidity/Origin.sol:AgentSecured":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/OriginEvents.sol\n\n/// @notice A collection of events emitted by the Origin contract\nabstract contract OriginEvents {\n    /**\n     * @notice Emitted when a new message is sent.\n     * @param messageHash   Hash of message; the leaf inserted to the Merkle tree for the message\n     * @param nonce         Nonce of sent message (starts from 1)\n     * @param destination   Destination domain\n     * @param message       Raw bytes of message\n     */\n    event Sent(bytes32 indexed messageHash, uint32 indexed nonce, uint32 indexed destination, bytes message);\n\n    /**\n     * @notice Emitted when a tip withdrawal is completed.\n     * @param actor     Actor address\n     * @param tip       Tip value, denominated in local domain's wei\n     */\n    event TipWithdrawalCompleted(address actor, uint256 tip);\n}\n\n// contracts/events/StateHubEvents.sol\n\n/// @notice A collection of events emitted by the StateHub contract\nabstract contract StateHubEvents {\n    /**\n     * @notice Emitted when a new Origin State is saved after a message was sent.\n     * @param state     Raw payload with state data\n     */\n    event StateSaved(bytes state);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n    /**\n     * @notice Check that a given state is valid: matches the historical state of Origin contract.\n     * Note: any Agent including an invalid state in their snapshot will be slashed\n     * upon providing the snapshot and agent signature for it to Origin contract.\n     * @dev Will revert if any of these is true:\n     *  - State payload is not properly formatted.\n     * @param statePayload      Raw payload with state data\n     * @return isValid          Whether the provided state is valid\n     */\n    function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns the amount of saved states so far.\n     * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n     */\n    function statesAmount() external view returns (uint256);\n\n    /**\n     * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @return statePayload     Raw payload with the latest state data\n     */\n    function suggestLatestState() external view returns (bytes memory statePayload);\n\n    /**\n     * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @param nonce             Historical nonce to form a state\n     * @return statePayload     Raw payload with historical state data\n     */\n    function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/InterfaceGasOracle.sol\n\ninterface InterfaceGasOracle {\n    /**\n     * @notice Fetches the latest gas data for the chain from `Destination` contract,\n     * and uses it to update the oracle values for the requested chain.\n     * @param domain    Domain to update the gas data for\n     */\n    function updateGasData(uint32 domain) external;\n\n    /**\n     * @notice Returns the gas data for the local chain.\n     */\n    function getGasData() external view returns (uint256 paddedGasData);\n\n    /**\n     * @notice Returns the gas data for the given domain, in the decoded format.\n     * @param domain        Domain of chain to get gas data for\n     * @return gasPrice     Gas price for the chain (in Wei per gas unit)\n     * @return dataPrice    Calldata price (in Wei per byte of content)\n     * @return execBuffer   Tx fee safety buffer for message execution (in Wei)\n     * @return amortAttCost Amortized cost for attestation submission (in Wei)\n     * @return etherPrice   Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n     * @return markup       Markup for the message execution (in BWAD)\n     */\n    function getDecodedGasData(uint32 domain)\n        external\n        view\n        returns (\n            uint256 gasPrice,\n            uint256 dataPrice,\n            uint256 execBuffer,\n            uint256 amortAttCost,\n            uint256 etherPrice,\n            uint256 markup\n        );\n\n    /**\n     * @notice Returns the minimum tips for sending a message to a given destination.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return paddedTips       Padded encoded minimum tips information\n     */\n    function getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 paddedTips);\n}\n\n// contracts/interfaces/InterfaceOrigin.sol\n\ninterface InterfaceOrigin {\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /**\n     * @notice Send a message to the recipient located on destination domain.\n     * @dev Recipient has to conform to IMessageRecipient interface, otherwise message won't be delivered.\n     * Will revert if any of these is true:\n     * - `destination` is equal to contract's local domain\n     * - `content` length is greater than `MAX_CONTENT_BYTES`\n     * - `msg.value` is lower than value of minimum tips for the given message\n     * @param destination           Domain of destination chain\n     * @param recipient             Address of recipient on destination chain as bytes32\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param paddedRequest         Padded encoded message execution request on destination chain\n     * @param content               Raw bytes content of message\n     * @return messageNonce         Nonce of the sent message\n     * @return messageHash          Hash of the sent message\n     */\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable returns (uint32 messageNonce, bytes32 messageHash);\n\n    /**\n     * @notice Send a manager message to the destination domain.\n     * @dev This could only be called by AgentManager, which takes care of encoding the calldata payload.\n     * Note: (msgOrigin, proofMaturity) security args will be added to payload on the destination chain\n     * so that the AgentManager could verify where the Manager Message came from and how mature is the proof.\n     * Note: function is not payable, as no tips are required for sending a manager message.\n     * Will revert if `destination` is equal to contract's local domain.\n     * @param destination           Domain of destination chain\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param payload               Payload for calling AgentManager on destination chain (with extra security args)\n     */\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        returns (uint32 messageNonce, bytes32 messageHash);\n\n    // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Withdraws locked base message tips to the recipient.\n     * @dev Could only be called by a local AgentManager.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function withdrawTips(address recipient, uint256 amount) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the minimum tips value for sending a message to a given destination.\n     * @dev Using at least `tipsValue` as `msg.value` for `sendBaseMessage()`\n     * will guarantee that the message will be accepted.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return tipsValue        Minimum tips value for a message to be accepted\n     */\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue);\n}\n\n// contracts/libs/Constants.sol\n\n// Here we define common constants to enable their easier reusing later.\n\n// ══════════════════════════════════ MERKLE ═══════════════════════════════════\n/// @dev Height of the Agent Merkle Tree\nuint256 constant AGENT_TREE_HEIGHT = 32;\n/// @dev Height of the Origin Merkle Tree\nuint256 constant ORIGIN_TREE_HEIGHT = 32;\n/// @dev Height of the Snapshot Merkle Tree. Allows up to 64 leafs, e.g. up to 32 states\nuint256 constant SNAPSHOT_TREE_HEIGHT = 6;\n// ══════════════════════════════════ STRUCTS ══════════════════════════════════\n/// @dev See Attestation.sol: (bytes32,bytes32,uint32,uint40,uint40): 32+32+4+5+5\nuint256 constant ATTESTATION_LENGTH = 78;\n/// @dev See GasData.sol: (uint16,uint16,uint16,uint16,uint16,uint16): 2+2+2+2+2+2\nuint256 constant GAS_DATA_LENGTH = 12;\n/// @dev See Receipt.sol: (uint32,uint32,bytes32,bytes32,uint8,address,address,address): 4+4+32+32+1+20+20+20\nuint256 constant RECEIPT_LENGTH = 133;\n/// @dev See State.sol: (bytes32,uint32,uint32,uint40,uint40,GasData): 32+4+4+5+5+len(GasData)\nuint256 constant STATE_LENGTH = 50 + GAS_DATA_LENGTH;\n/// @dev Maximum amount of states in a single snapshot. Each state produces two leafs in the tree\nuint256 constant SNAPSHOT_MAX_STATES = 1 \u003c\u003c (SNAPSHOT_TREE_HEIGHT - 1);\n// ══════════════════════════════════ MESSAGE ══════════════════════════════════\n/// @dev See Header.sol: (uint8,uint32,uint32,uint32,uint32): 1+4+4+4+4\nuint256 constant HEADER_LENGTH = 17;\n/// @dev See Request.sol: (uint96,uint64,uint32): 12+8+4\nuint256 constant REQUEST_LENGTH = 24;\n/// @dev See Tips.sol: (uint64,uint64,uint64,uint64): 8+8+8+8\nuint256 constant TIPS_LENGTH = 32;\n/// @dev The amount of discarded last bits when encoding tip values\nuint256 constant TIPS_GRANULARITY = 32;\n/// @dev Tip values could be only the multiples of TIPS_MULTIPLIER\nuint256 constant TIPS_MULTIPLIER = 1 \u003c\u003c TIPS_GRANULARITY;\n// ══════════════════════════════ STATEMENT SALTS ══════════════════════════════\n/// @dev Salts for signing various statements\nbytes32 constant ATTESTATION_VALID_SALT = keccak256(\"ATTESTATION_VALID_SALT\");\nbytes32 constant ATTESTATION_INVALID_SALT = keccak256(\"ATTESTATION_INVALID_SALT\");\nbytes32 constant RECEIPT_VALID_SALT = keccak256(\"RECEIPT_VALID_SALT\");\nbytes32 constant RECEIPT_INVALID_SALT = keccak256(\"RECEIPT_INVALID_SALT\");\nbytes32 constant SNAPSHOT_VALID_SALT = keccak256(\"SNAPSHOT_VALID_SALT\");\nbytes32 constant STATE_INVALID_SALT = keccak256(\"STATE_INVALID_SALT\");\n// ═════════════════════════════════ PROTOCOL ══════════════════════════════════\n/// @dev Optimistic period for new agent roots in LightManager\nuint32 constant AGENT_ROOT_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Timeout between the agent root could be proposed and resolved in LightManager\nuint32 constant AGENT_ROOT_PROPOSAL_TIMEOUT = 12 hours;\nuint32 constant BONDING_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Amount of time that the Notary will not be considered active after they won a dispute\nuint32 constant DISPUTE_TIMEOUT_NOTARY = 12 hours;\n/// @dev Amount of time without fresh data from Notaries before contract owner can resolve stuck disputes manually\nuint256 constant FRESH_DATA_TIMEOUT = 4 hours;\n/// @dev Maximum bytes per message = 2 KiB (somewhat arbitrarily set to begin)\nuint256 constant MAX_CONTENT_BYTES = 2 * 2 ** 10;\n/// @dev Maximum value for the summit tip that could be set in GasOracle\nuint256 constant MAX_SUMMIT_TIP = 0.01 ether;\n\n// contracts/libs/Errors.sol\n\n// ══════════════════════════════ INVALID CALLER ═══════════════════════════════\n\nerror CallerNotAgentManager();\nerror CallerNotDestination();\nerror CallerNotInbox();\nerror CallerNotSummit();\n\n// ══════════════════════════════ INCORRECT DATA ═══════════════════════════════\n\nerror IncorrectAttestation();\nerror IncorrectAgentDomain();\nerror IncorrectAgentIndex();\nerror IncorrectAgentProof();\nerror IncorrectAgentRoot();\nerror IncorrectDataHash();\nerror IncorrectDestinationDomain();\nerror IncorrectOriginDomain();\nerror IncorrectSnapshotProof();\nerror IncorrectSnapshotRoot();\nerror IncorrectState();\nerror IncorrectStatesAmount();\nerror IncorrectTipsProof();\nerror IncorrectVersionLength();\n\nerror IncorrectNonce();\nerror IncorrectSender();\nerror IncorrectRecipient();\n\nerror FlagOutOfRange();\nerror IndexOutOfRange();\nerror NonceOutOfRange();\n\nerror OutdatedNonce();\n\nerror UnformattedAttestation();\nerror UnformattedAttestationReport();\nerror UnformattedBaseMessage();\nerror UnformattedCallData();\nerror UnformattedCallDataPrefix();\nerror UnformattedMessage();\nerror UnformattedReceipt();\nerror UnformattedReceiptReport();\nerror UnformattedSignature();\nerror UnformattedSnapshot();\nerror UnformattedState();\nerror UnformattedStateReport();\n\n// ═══════════════════════════════ MERKLE TREES ════════════════════════════════\n\nerror LeafNotProven();\nerror MerkleTreeFull();\nerror NotEnoughLeafs();\nerror TreeHeightTooLow();\n\n// ═════════════════════════════ OPTIMISTIC PERIOD ═════════════════════════════\n\nerror BaseClientOptimisticPeriod();\nerror MessageOptimisticPeriod();\nerror SlashAgentOptimisticPeriod();\nerror WithdrawTipsOptimisticPeriod();\nerror ZeroProofMaturity();\n\n// ═══════════════════════════════ AGENT MANAGER ═══════════════════════════════\n\nerror AgentNotGuard();\nerror AgentNotNotary();\n\nerror AgentCantBeAdded();\nerror AgentNotActive();\nerror AgentNotActiveNorUnstaking();\nerror AgentNotFraudulent();\nerror AgentNotUnstaking();\nerror AgentUnknown();\n\nerror AgentRootNotProposed();\nerror AgentRootTimeoutNotOver();\n\nerror NotStuck();\n\nerror DisputeAlreadyResolved();\nerror DisputeNotOpened();\nerror DisputeTimeoutNotOver();\nerror GuardInDispute();\nerror NotaryInDispute();\n\nerror MustBeSynapseDomain();\nerror SynapseDomainForbidden();\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\nerror AlreadyExecuted();\nerror AlreadyFailed();\nerror DuplicatedSnapshotRoot();\nerror IncorrectMagicValue();\nerror GasLimitTooLow();\nerror GasSuppliedTooLow();\n\n// ══════════════════════════════════ ORIGIN ═══════════════════════════════════\n\nerror ContentLengthTooBig();\nerror EthTransferFailed();\nerror InsufficientEthBalance();\n\n// ════════════════════════════════ GAS ORACLE ═════════════════════════════════\n\nerror LocalGasDataNotSet();\nerror RemoteGasDataNotSet();\n\n// ═══════════════════════════════════ TIPS ════════════════════════════════════\n\nerror SummitTipTooHigh();\nerror TipsClaimMoreThanEarned();\nerror TipsClaimZero();\nerror TipsOverflow();\nerror TipsValueTooLow();\n\n// ════════════════════════════════ MEMORY VIEW ════════════════════════════════\n\nerror IndexedTooMuch();\nerror ViewOverrun();\nerror OccupiedMemory();\nerror UnallocatedMemory();\nerror PrecompileOutOfGas();\n\n// ═════════════════════════════════ MULTICALL ═════════════════════════════════\n\nerror MulticallFailed();\n\n// contracts/libs/TypeCasts.sol\n\nlibrary TypeCasts {\n    // alignment preserving cast\n    function addressToBytes32(address addr) internal pure returns (bytes32) {\n        return bytes32(uint256(uint160(addr)));\n    }\n\n    // alignment preserving cast\n    function bytes32ToAddress(bytes32 buf) internal pure returns (address) {\n        return address(uint160(uint256(buf)));\n    }\n}\n\n// contracts/libs/stack/Number.sol\n\n/// Number is a compact representation of uint256, that is fit into 16 bits\n/// with the maximum relative error under 0.4%.\ntype Number is uint16;\n\nusing NumberLib for Number global;\n\n/// # Number\n/// Library for compact representation of uint256 numbers.\n/// - Number is stored using mantissa and exponent, each occupying 8 bits.\n/// - Numbers under 2**8 are stored as `mantissa` with `exponent = 0xFF`.\n/// - Numbers at least 2**8 are approximated as `(256 + mantissa) \u003c\u003c exponent`\n/// \u003e - `0 \u003c= mantissa \u003c 256`\n/// \u003e - `0 \u003c= exponent \u003c= 247` (`256 * 2**248` doesn't fit into uint256)\n/// # Number stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type  | Bytes |\n/// | ---------- | -------- | ----- | ----- |\n/// | (002..001] | mantissa | uint8 | 1     |\n/// | (001..000] | exponent | uint8 | 1     |\n\nlibrary NumberLib {\n    /// @dev Amount of bits to shift to mantissa field\n    uint16 private constant SHIFT_MANTISSA = 8;\n\n    /// @notice For bwad math (binary wad) we use 2**64 as \"wad\" unit.\n    /// @dev We are using not using 10**18 as wad, because it is not stored precisely in NumberLib.\n    uint256 internal constant BWAD_SHIFT = 64;\n    uint256 internal constant BWAD = 1 \u003c\u003c BWAD_SHIFT;\n    /// @notice ~0.1% in bwad units.\n    uint256 internal constant PER_MILLE_SHIFT = BWAD_SHIFT - 10;\n    uint256 internal constant PER_MILLE = 1 \u003c\u003c PER_MILLE_SHIFT;\n\n    /// @notice Compresses uint256 number into 16 bits.\n    function compress(uint256 value) internal pure returns (Number) {\n        // Find `msb` such as `2**msb \u003c= value \u003c 2**(msb + 1)`\n        uint256 msb = mostSignificantBit(value);\n        // We want to preserve 9 bits of precision.\n        // The highest bit is always 1, so we can skip it.\n        // The remaining 8 highest bits are stored as mantissa.\n        if (msb \u003c 8) {\n            // Value is less than 2**8, so we can use value as mantissa with \"-1\" exponent.\n            return _encode(uint8(value), 0xFF);\n        } else {\n            // We use `msb - 8` as exponent otherwise. Note that `exponent \u003e= 0`.\n            unchecked {\n                uint256 exponent = msb - 8;\n                // Shifting right by `msb-8` bits will shift the \"remaining 8 highest bits\" into the 8 lowest bits.\n                // uint8() will truncate the highest bit.\n                return _encode(uint8(value \u003e\u003e exponent), uint8(exponent));\n            }\n        }\n    }\n\n    /// @notice Decompresses 16 bits number into uint256.\n    /// @dev The outcome is an approximation of the original number: `(value - value / 256) \u003c number \u003c= value`.\n    function decompress(Number number) internal pure returns (uint256 value) {\n        // Isolate 8 highest bits as the mantissa.\n        uint256 mantissa = Number.unwrap(number) \u003e\u003e SHIFT_MANTISSA;\n        // This will truncate the highest bits, leaving only the exponent.\n        uint256 exponent = uint8(Number.unwrap(number));\n        if (exponent == 0xFF) {\n            return mantissa;\n        } else {\n            unchecked {\n                return (256 + mantissa) \u003c\u003c (exponent);\n            }\n        }\n    }\n\n    /// @dev Returns the most significant bit of `x`\n    /// https://solidity-by-example.org/bitwise/\n    function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\n        // To find `msb` we determine it bit by bit, starting from the highest one.\n        // `0 \u003c= msb \u003c= 255`, so we start from the highest bit, 1\u003c\u003c7 == 128.\n        // If `x` is at least 2**128, then the highest bit of `x` is at least 128.\n        // solhint-disable no-inline-assembly\n        assembly {\n            // `f` is set to 1\u003c\u003c7 if `x \u003e= 2**128` and to 0 otherwise.\n            let f := shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\n            // If `x \u003e= 2**128` then set `msb` highest bit to 1 and shift `x` right by 128.\n            // Otherwise, `msb` remains 0 and `x` remains unchanged.\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        // `x` is now at most 2**128 - 1. Continue the same way, the next highest bit is 1\u003c\u003c6 == 64.\n        assembly {\n            // `f` is set to 1\u003c\u003c6 if `x \u003e= 2**64` and to 0 otherwise.\n            let f := shl(6, gt(x, 0xFFFFFFFFFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c5 if `x \u003e= 2**32` and to 0 otherwise.\n            let f := shl(5, gt(x, 0xFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c4 if `x \u003e= 2**16` and to 0 otherwise.\n            let f := shl(4, gt(x, 0xFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c3 if `x \u003e= 2**8` and to 0 otherwise.\n            let f := shl(3, gt(x, 0xFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c2 if `x \u003e= 2**4` and to 0 otherwise.\n            let f := shl(2, gt(x, 0xF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c1 if `x \u003e= 2**2` and to 0 otherwise.\n            let f := shl(1, gt(x, 0x3))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1 if `x \u003e= 2**1` and to 0 otherwise.\n            let f := gt(x, 0x1)\n            msb := or(msb, f)\n        }\n    }\n\n    /// @dev Wraps (mantissa, exponent) pair into Number.\n    function _encode(uint8 mantissa, uint8 exponent) private pure returns (Number) {\n        // Casts below are upcasts, so they are safe.\n        return Number.wrap(uint16(mantissa) \u003c\u003c SHIFT_MANTISSA | uint16(exponent));\n    }\n}\n\n// contracts/libs/stack/Request.sol\n\n/// Request is encoded data with \"message execution request\".\ntype Request is uint192;\n\nusing RequestLib for Request global;\n\n/// Library for formatting _the request part_ of _the base messages_.\n/// - Request represents a message sender requirements for the message execution on the destination chain.\n/// - Request occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n/// \u003e gasDrop field is included for future compatibility and is ignored at the moment.\n///\n/// # Request stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type   | Bytes | Description                                          |\n/// | ---------- | -------- | ------ | ----- | ---------------------------------------------------- |\n/// | (024..012] | gasDrop  | uint96 | 12    | Minimum amount of gas token to drop to the recipient |\n/// | (012..004] | gasLimit | uint64 | 8     | Minimum amount of gas units to supply for execution  |\n/// | (004..000] | version  | uint32 | 4     | Base message version to pass to the recipient        |\n\nlibrary RequestLib {\n    /// @dev Amount of bits to shift to gasDrop field\n    uint192 private constant SHIFT_GAS_DROP = 12 * 8;\n    /// @dev Amount of bits to shift to gasLimit field\n    uint192 private constant SHIFT_GAS_LIMIT = 4 * 8;\n\n    /// @notice Returns an encoded request with the given fields\n    /// @param gasDrop_     Minimum amount of gas token to drop to the recipient (ignored at the moment)\n    /// @param gasLimit_    Minimum amount of gas units to supply for execution\n    /// @param version_     Base message version to pass to the recipient\n    function encodeRequest(uint96 gasDrop_, uint64 gasLimit_, uint32 version_) internal pure returns (Request) {\n        // Casts below are upcasts, so they are safe\n        return Request.wrap(uint192(gasDrop_) \u003c\u003c SHIFT_GAS_DROP | uint192(gasLimit_) \u003c\u003c SHIFT_GAS_LIMIT | version_);\n    }\n\n    /// @notice Wraps the padded encoded request into a Request-typed value.\n    /// @dev The \"padded\" request is simply an encoded request casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded requests\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedRequest) internal pure returns (Request) {\n        // Casting to uint192 will truncate the highest bits, which is the behavior we want\n        return Request.wrap(uint192(paddedRequest));\n    }\n\n    /// @notice Returns the requested of gas token to drop to the recipient.\n    function gasDrop(Request request) internal pure returns (uint96) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return uint96(Request.unwrap(request) \u003e\u003e SHIFT_GAS_DROP);\n    }\n\n    /// @notice Returns the requested minimum amount of gas units to supply for execution.\n    function gasLimit(Request request) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Request.unwrap(request) \u003e\u003e SHIFT_GAS_LIMIT);\n    }\n\n    /// @notice Returns the requested base message version to pass to the recipient.\n    function version(Request request) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Request.unwrap(request));\n    }\n}\n\n// node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        require(value \u003c= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        require(value \u003c= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        require(value \u003c= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value \u003c= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        require(value \u003c= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        require(value \u003c= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        require(value \u003c= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        require(value \u003c= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        require(value \u003c= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        require(value \u003c= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        require(value \u003c= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        require(value \u003c= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        require(value \u003c= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        require(value \u003c= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        require(value \u003c= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value \u003c= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        require(value \u003c= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        require(value \u003c= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        require(value \u003c= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value \u003c= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        require(value \u003c= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        require(value \u003c= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        require(value \u003c= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value \u003c= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        require(value \u003c= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        require(value \u003c= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        require(value \u003c= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value \u003c= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        require(value \u003c= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value \u003c= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value \u003c= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     *\n     * _Available since v3.0._\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value \u003e= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     *\n     * _Available since v3.0._\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value \u003c= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     *\n     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length \u003e 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance \u003e= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance \u003e= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length \u003e 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n\n// contracts/base/MultiCallable.sol\n\n/// @notice Collection of Multicall utilities. Fork of Multicall3:\n/// https://github.com/mds1/multicall/blob/master/src/Multicall3.sol\nabstract contract MultiCallable {\n    struct Call {\n        bool allowFailure;\n        bytes callData;\n    }\n\n    struct Result {\n        bool success;\n        bytes returnData;\n    }\n\n    /// @notice Aggregates a few calls to this contract into one multicall without modifying `msg.sender`.\n    function multicall(Call[] calldata calls) external returns (Result[] memory callResults) {\n        uint256 amount = calls.length;\n        callResults = new Result[](amount);\n        Call calldata call_;\n        for (uint256 i = 0; i \u003c amount;) {\n            call_ = calls[i];\n            Result memory result = callResults[i];\n            // We perform a delegate call to ourselves here. Delegate call does not modify `msg.sender`, so\n            // this will have the same effect as if `msg.sender` performed all the calls themselves one by one.\n            // solhint-disable-next-line avoid-low-level-calls\n            (result.success, result.returnData) = address(this).delegatecall(call_.callData);\n            // solhint-disable-next-line no-inline-assembly\n            assembly {\n                // Revert if the call fails and failure is not allowed\n                // `allowFailure := calldataload(call_)` and `success := mload(result)`\n                if iszero(or(calldataload(call_), mload(result))) {\n                    // Revert with `0x4d6a2328` (function selector for `MulticallFailed()`)\n                    mstore(0x00, 0x4d6a232800000000000000000000000000000000000000000000000000000000)\n                    revert(0x00, 0x04)\n                }\n            }\n            unchecked {\n                ++i;\n            }\n        }\n    }\n}\n\n// contracts/base/Version.sol\n\n/**\n * @title Versioned\n * @notice Version getter for contracts. Doesn't use any storage slots, meaning\n * it will never cause any troubles with the upgradeable contracts. For instance, this contract\n * can be added or removed from the inheritance chain without shifting the storage layout.\n */\nabstract contract Versioned {\n    /**\n     * @notice Struct that is mimicking the storage layout of a string with 32 bytes or less.\n     * Length is limited by 32, so the whole string payload takes two memory words:\n     * @param length    String length\n     * @param data      String characters\n     */\n    struct _ShortString {\n        uint256 length;\n        bytes32 data;\n    }\n\n    /// @dev Length of the \"version string\"\n    uint256 private immutable _length;\n    /// @dev Bytes representation of the \"version string\".\n    /// Strings with length over 32 are not supported!\n    bytes32 private immutable _data;\n\n    constructor(string memory version_) {\n        _length = bytes(version_).length;\n        if (_length \u003e 32) revert IncorrectVersionLength();\n        // bytes32 is left-aligned =\u003e this will store the byte representation of the string\n        // with the trailing zeroes to complete the 32-byte word\n        _data = bytes32(bytes(version_));\n    }\n\n    function version() external view returns (string memory versionString) {\n        // Load the immutable values to form the version string\n        _ShortString memory str = _ShortString(_length, _data);\n        // The only way to do this cast is doing some dirty assembly\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            versionString := str\n        }\n    }\n}\n\n// contracts/libs/ChainContext.sol\n\n/// @notice Library for accessing chain context variables as tightly packed integers.\n/// Messaging contracts should rely on this library for accessing chain context variables\n/// instead of doing the casting themselves.\nlibrary ChainContext {\n    using SafeCast for uint256;\n\n    /// @notice Returns the current block number as uint40.\n    /// @dev Reverts if block number is greater than 40 bits, which is not supposed to happen\n    /// until the block.timestamp overflows (assuming block time is at least 1 second).\n    function blockNumber() internal view returns (uint40) {\n        return block.number.toUint40();\n    }\n\n    /// @notice Returns the current block timestamp as uint40.\n    /// @dev Reverts if block timestamp is greater than 40 bits, which is\n    /// supposed to happen approximately in year 36835.\n    function blockTimestamp() internal view returns (uint40) {\n        return block.timestamp.toUint40();\n    }\n\n    /// @notice Returns the chain id as uint32.\n    /// @dev Reverts if chain id is greater than 32 bits, which is not\n    /// supposed to happen in production.\n    function chainId() internal view returns (uint32) {\n        return block.chainid.toUint32();\n    }\n}\n\n// contracts/libs/Structures.sol\n\n// Here we define common enums and structures to enable their easier reusing later.\n\n// ═══════════════════════════════ AGENT STATUS ════════════════════════════════\n\n/// @dev Potential statuses for the off-chain bonded agent:\n/// - Unknown: never provided a bond =\u003e signature not valid\n/// - Active: has a bond in BondingManager =\u003e signature valid\n/// - Unstaking: has a bond in BondingManager, initiated the unstaking =\u003e signature not valid\n/// - Resting: used to have a bond in BondingManager, successfully unstaked =\u003e signature not valid\n/// - Fraudulent: proven to commit fraud, value in Merkle Tree not updated =\u003e signature not valid\n/// - Slashed: proven to commit fraud, value in Merkle Tree was updated =\u003e signature not valid\n/// Unstaked agent could later be added back to THE SAME domain by staking a bond again.\n/// Honest agent: Unknown -\u003e Active -\u003e unstaking -\u003e Resting -\u003e Active ...\n/// Malicious agent: Unknown -\u003e Active -\u003e Fraudulent -\u003e Slashed\n/// Malicious agent: Unknown -\u003e Active -\u003e Unstaking -\u003e Fraudulent -\u003e Slashed\nenum AgentFlag {\n    Unknown,\n    Active,\n    Unstaking,\n    Resting,\n    Fraudulent,\n    Slashed\n}\n\n/// @notice Struct for storing an agent in the BondingManager contract.\nstruct AgentStatus {\n    AgentFlag flag;\n    uint32 domain;\n    uint32 index;\n}\n// 184 bits available for tight packing\n\nusing StructureUtils for AgentStatus global;\n\n/// @notice Potential statuses of an agent in terms of being in dispute\n/// - None: agent is not in dispute\n/// - Pending: agent is in unresolved dispute\n/// - Slashed: agent was in dispute that lead to agent being slashed\n/// Note: agent who won the dispute has their status reset to None\nenum DisputeFlag {\n    None,\n    Pending,\n    Slashed\n}\n\n/// @notice Struct for storing dispute status of an agent.\n/// @param flag         Dispute flag: None/Pending/Slashed.\n/// @param openedAt     Timestamp when the latest agent dispute was opened (zero if not opened).\n/// @param resolvedAt   Timestamp when the latest agent dispute was resolved (zero if not resolved).\nstruct DisputeStatus {\n    DisputeFlag flag;\n    uint40 openedAt;\n    uint40 resolvedAt;\n}\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\n/// @notice Struct representing the status of Destination contract.\n/// @param snapRootTime     Timestamp when latest snapshot root was accepted\n/// @param agentRootTime    Timestamp when latest agent root was accepted\n/// @param notaryIndex      Index of Notary who signed the latest agent root\nstruct DestinationStatus {\n    uint40 snapRootTime;\n    uint40 agentRootTime;\n    uint32 notaryIndex;\n}\n\n// ═══════════════════════════════ EXECUTION HUB ═══════════════════════════════\n\n/// @notice Potential statuses of the message in Execution Hub.\n/// - None: there hasn't been a valid attempt to execute the message yet\n/// - Failed: there was a valid attempt to execute the message, but recipient reverted\n/// - Success: there was a valid attempt to execute the message, and recipient did not revert\n/// Note: message can be executed until its status is Success\nenum MessageStatus {\n    None,\n    Failed,\n    Success\n}\n\nlibrary StructureUtils {\n    /// @notice Checks that Agent is Active\n    function verifyActive(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active) {\n            revert AgentNotActive();\n        }\n    }\n\n    /// @notice Checks that Agent is Unstaking\n    function verifyUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Unstaking) {\n            revert AgentNotUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Active or Unstaking\n    function verifyActiveUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active \u0026\u0026 status.flag != AgentFlag.Unstaking) {\n            revert AgentNotActiveNorUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Fraudulent\n    function verifyFraudulent(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Fraudulent) {\n            revert AgentNotFraudulent();\n        }\n    }\n\n    /// @notice Checks that Agent is not Unknown\n    function verifyKnown(AgentStatus memory status) internal pure {\n        if (status.flag == AgentFlag.Unknown) {\n            revert AgentUnknown();\n        }\n    }\n}\n\n// contracts/libs/memory/MemView.sol\n\n/// @dev MemView is an untyped view over a portion of memory to be used instead of `bytes memory`\ntype MemView is uint256;\n\n/// @dev Attach library functions to MemView\nusing MemViewLib for MemView global;\n\n/// @notice Library for operations with the memory views.\n/// Forked from https://github.com/summa-tx/memview-sol with several breaking changes:\n/// - The codebase is ported to Solidity 0.8\n/// - Custom errors are added\n/// - The runtime type checking is replaced with compile-time check provided by User-Defined Value Types\n///   https://docs.soliditylang.org/en/latest/types.html#user-defined-value-types\n/// - uint256 is used as the underlying type for the \"memory view\" instead of bytes29.\n///   It is wrapped into MemView custom type in order not to be confused with actual integers.\n/// - Therefore the \"type\" field is discarded, allowing to allocate 16 bytes for both view location and length\n/// - The documentation is expanded\n/// - Library functions unused by the rest of the codebase are removed\n//  - Very pretty code separators are added :)\nlibrary MemViewLib {\n    /// @notice Stack layout for uint256 (from highest bits to lowest)\n    /// (32 .. 16]      loc     16 bytes    Memory address of underlying bytes\n    /// (16 .. 00]      len     16 bytes    Length of underlying bytes\n\n    // ═══════════════════════════════════════════ BUILDING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Instantiate a new untyped memory view. This should generally not be called directly.\n     * Prefer `ref` wherever possible.\n     * @param loc_          The memory address\n     * @param len_          The length\n     * @return The new view with the specified location and length\n     */\n    function build(uint256 loc_, uint256 len_) internal pure returns (MemView) {\n        uint256 end_ = loc_ + len_;\n        // Make sure that a view is not constructed that points to unallocated memory\n        // as this could be indicative of a buffer overflow attack\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            if gt(end_, mload(0x40)) { end_ := 0 }\n        }\n        if (end_ == 0) {\n            revert UnallocatedMemory();\n        }\n        return _unsafeBuildUnchecked(loc_, len_);\n    }\n\n    /**\n     * @notice Instantiate a memory view from a byte array.\n     * @dev Note that due to Solidity memory representation, it is not possible to\n     * implement a deref, as the `bytes` type stores its len in memory.\n     * @param arr           The byte array\n     * @return The memory view over the provided byte array\n     */\n    function ref(bytes memory arr) internal pure returns (MemView) {\n        uint256 len_ = arr.length;\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 loc_;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // We add 0x20, so that the view starts exactly where the array data starts\n            loc_ := add(arr, 0x20)\n        }\n        return build(loc_, len_);\n    }\n\n    // ════════════════════════════════════════════ CLONING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to the new memory.\n     * @param memView       The memory view\n     * @return arr          The cloned byte array\n     */\n    function clone(MemView memView) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        unchecked {\n            _unsafeCopyTo(memView, ptr + 0x20);\n        }\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 len_ = memView.len();\n        uint256 footprint_ = memView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    /**\n     * @notice Copies all views, joins them into a new bytearray.\n     * @param memViews      The memory views\n     * @return arr          The new byte array with joined data behind the given views\n     */\n    function join(MemView[] memory memViews) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        MemView newView;\n        unchecked {\n            newView = _unsafeJoin(memViews, ptr + 0x20);\n        }\n        uint256 len_ = newView.len();\n        uint256 footprint_ = newView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    // ══════════════════════════════════════════ INSPECTING MEMORY VIEW ═══════════════════════════════════════════════\n\n    /**\n     * @notice Returns the memory address of the underlying bytes.\n     * @param memView       The memory view\n     * @return loc_         The memory address\n     */\n    function loc(MemView memView) internal pure returns (uint256 loc_) {\n        // loc is stored in the highest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u003e\u003e 128;\n    }\n\n    /**\n     * @notice Returns the number of bytes of the view.\n     * @param memView       The memory view\n     * @return len_         The length of the view\n     */\n    function len(MemView memView) internal pure returns (uint256 len_) {\n        // len is stored in the lowest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u0026 type(uint128).max;\n    }\n\n    /**\n     * @notice Returns the endpoint of `memView`.\n     * @param memView       The memory view\n     * @return end_         The endpoint of `memView`\n     */\n    function end(MemView memView) internal pure returns (uint256 end_) {\n        // The endpoint never overflows uint128, let alone uint256, so we could use unchecked math here\n        unchecked {\n            return memView.loc() + memView.len();\n        }\n    }\n\n    /**\n     * @notice Returns the number of memory words this memory view occupies, rounded up.\n     * @param memView       The memory view\n     * @return words_       The number of memory words\n     */\n    function words(MemView memView) internal pure returns (uint256 words_) {\n        // returning ceil(length / 32.0)\n        unchecked {\n            return (memView.len() + 31) \u003e\u003e 5;\n        }\n    }\n\n    /**\n     * @notice Returns the in-memory footprint of a fresh copy of the view.\n     * @param memView       The memory view\n     * @return footprint_   The in-memory footprint of a fresh copy of the view.\n     */\n    function footprint(MemView memView) internal pure returns (uint256 footprint_) {\n        // words() * 32\n        return memView.words() \u003c\u003c 5;\n    }\n\n    // ════════════════════════════════════════════ HASHING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the keccak256 hash of the underlying memory\n     * @param memView       The memory view\n     * @return digest       The keccak256 hash of the underlying memory\n     */\n    function keccak(MemView memView) internal pure returns (bytes32 digest) {\n        uint256 loc_ = memView.loc();\n        uint256 len_ = memView.len();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            digest := keccak256(loc_, len_)\n        }\n    }\n\n    /**\n     * @notice Adds a salt to the keccak256 hash of the underlying data and returns the keccak256 hash of the\n     * resulting data.\n     * @param memView       The memory view\n     * @return digestSalted keccak256(salt, keccak256(memView))\n     */\n    function keccakSalted(MemView memView, bytes32 salt) internal pure returns (bytes32 digestSalted) {\n        return keccak256(bytes.concat(salt, memView.keccak()));\n    }\n\n    // ════════════════════════════════════════════ SLICING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Safe slicing without memory modification.\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the given index\n     */\n    function slice(MemView memView, uint256 index_, uint256 len_) internal pure returns (MemView) {\n        uint256 loc_ = memView.loc();\n        // Ensure it doesn't overrun the view\n        if (loc_ + index_ + len_ \u003e memView.end()) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // loc_ + index_ \u003c= memView.end()\n            return build({loc_: loc_ + index_, len_: len_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing bytes from `index` to end(memView).\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @return The new view for the slice starting from the given index until the initial view endpoint\n     */\n    function sliceFrom(MemView memView, uint256 index_) internal pure returns (MemView) {\n        uint256 len_ = memView.len();\n        // Ensure it doesn't overrun the view\n        if (index_ \u003e len_) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // index_ \u003c= len_ =\u003e memView.loc() + index_ \u003c= memView.loc() + memView.len() == memView.end()\n            return build({loc_: memView.loc() + index_, len_: len_ - index_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the first `len` bytes.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the initial view beginning\n     */\n    function prefix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        return memView.slice({index_: 0, len_: len_});\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the last `len` byte.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length until the initial view endpoint\n     */\n    function postfix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        uint256 viewLen = memView.len();\n        // Ensure it doesn't overrun the view\n        if (len_ \u003e viewLen) {\n            revert ViewOverrun();\n        }\n        // Could do the unchecked math due to the check above\n        uint256 index_;\n        unchecked {\n            index_ = viewLen - len_;\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // len_ \u003c= memView.len() =\u003e memView.loc() \u003c= loc_ \u003c= memView.end()\n            return build({loc_: memView.loc() + viewLen - len_, len_: len_});\n        }\n    }\n\n    // ═══════════════════════════════════════════ INDEXING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Load up to 32 bytes from the view onto the stack.\n     * @dev Returns a bytes32 with only the `bytes_` HIGHEST bytes set.\n     * This can be immediately cast to a smaller fixed-length byte array.\n     * To automatically cast to an integer, use `indexUint`.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return result       The 32 byte result having only `bytes_` highest bytes set\n     */\n    function index(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (bytes32 result) {\n        if (bytes_ == 0) {\n            return bytes32(0);\n        }\n        // Can't load more than 32 bytes to the stack in one go\n        if (bytes_ \u003e 32) {\n            revert IndexedTooMuch();\n        }\n        // The last indexed byte should be within view boundaries\n        if (index_ + bytes_ \u003e memView.len()) {\n            revert ViewOverrun();\n        }\n        uint256 bitLength = bytes_ \u003c\u003c 3; // bytes_ * 8\n        uint256 loc_ = memView.loc();\n        // Get a mask with `bitLength` highest bits set\n        uint256 mask;\n        // 0x800...00 binary representation is 100...00\n        // sar stands for \"signed arithmetic shift\": https://en.wikipedia.org/wiki/Arithmetic_shift\n        // sar(N-1, 100...00) = 11...100..00, with exactly N highest bits set to 1\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            mask := sar(sub(bitLength, 1), 0x8000000000000000000000000000000000000000000000000000000000000000)\n        }\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load a full word using index offset, and apply mask to ignore non-relevant bytes\n            result := and(mload(add(loc_, index_)), mask)\n        }\n    }\n\n    /**\n     * @notice Parse an unsigned integer from the view at `index`.\n     * @dev Requires that the view have \u003e= `bytes_` bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return The unsigned integer\n     */\n    function indexUint(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (uint256) {\n        bytes32 indexedBytes = memView.index(index_, bytes_);\n        // `index()` returns left-aligned `bytes_`, while integers are right-aligned\n        // Shifting here to right-align with the full 32 bytes word: need to shift right `(32 - bytes_)` bytes\n        unchecked {\n            // memView.index() reverts when bytes_ \u003e 32, thus unchecked math\n            return uint256(indexedBytes) \u003e\u003e ((32 - bytes_) \u003c\u003c 3);\n        }\n    }\n\n    /**\n     * @notice Parse an address from the view at `index`.\n     * @dev Requires that the view have \u003e= 20 bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @return The address\n     */\n    function indexAddress(MemView memView, uint256 index_) internal pure returns (address) {\n        // index 20 bytes as `uint160`, and then cast to `address`\n        return address(uint160(memView.indexUint(index_, 20)));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns a memory view over the specified memory location\n    /// without checking if it points to unallocated memory.\n    function _unsafeBuildUnchecked(uint256 loc_, uint256 len_) private pure returns (MemView) {\n        // There is no scenario where loc or len would overflow uint128, so we omit this check.\n        // We use the highest 128 bits to encode the location and the lowest 128 bits to encode the length.\n        return MemView.wrap((loc_ \u003c\u003c 128) | len_);\n    }\n\n    /**\n     * @notice Copy the view to a location, return an unsafe memory reference\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memView       The memory view\n     * @param newLoc        The new location to copy the underlying view data\n     * @return The memory view over the unsafe memory with the copied underlying data\n     */\n    function _unsafeCopyTo(MemView memView, uint256 newLoc) private view returns (MemView) {\n        uint256 len_ = memView.len();\n        uint256 oldLoc = memView.loc();\n\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (newLoc \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        bool res;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // use the identity precompile (0x04) to copy\n            res := staticcall(gas(), 0x04, oldLoc, len_, newLoc, len_)\n        }\n        if (!res) revert PrecompileOutOfGas();\n        return _unsafeBuildUnchecked({loc_: newLoc, len_: len_});\n    }\n\n    /**\n     * @notice Join the views in memory, return an unsafe reference to the memory.\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memViews      The memory views\n     * @return The conjoined view pointing to the new memory\n     */\n    function _unsafeJoin(MemView[] memory memViews, uint256 location) private view returns (MemView) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (location \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        // Copy the views to the specified location one by one, by tracking the amount of copied bytes so far\n        uint256 offset = 0;\n        for (uint256 i = 0; i \u003c memViews.length;) {\n            MemView memView = memViews[i];\n            // We can use the unchecked math here as location + sum(view.length) will never overflow uint256\n            unchecked {\n                _unsafeCopyTo(memView, location + offset);\n                offset += memView.len();\n                ++i;\n            }\n        }\n        return _unsafeBuildUnchecked({loc_: location, len_: offset});\n    }\n}\n\n// contracts/libs/merkle/MerkleMath.sol\n\nlibrary MerkleMath {\n    // ═════════════════════════════════════════ BASIC MERKLE CALCULATIONS ═════════════════════════════════════════════\n\n    /**\n     * @notice Calculates the merkle root for the given leaf and merkle proof.\n     * @dev Will revert if proof length exceeds the tree height.\n     * @param index     Index of `leaf` in tree\n     * @param leaf      Leaf of the merkle tree\n     * @param proof     Proof of inclusion of `leaf` in the tree\n     * @param height    Height of the merkle tree\n     * @return root_    Calculated Merkle Root\n     */\n    function proofRoot(uint256 index, bytes32 leaf, bytes32[] memory proof, uint256 height)\n        internal\n        pure\n        returns (bytes32 root_)\n    {\n        // Proof length could not exceed the tree height\n        uint256 proofLen = proof.length;\n        if (proofLen \u003e height) revert TreeHeightTooLow();\n        root_ = leaf;\n        /// @dev Apply unchecked to all ++h operations\n        unchecked {\n            // Go up the tree levels from the leaf following the proof\n            for (uint256 h = 0; h \u003c proofLen; ++h) {\n                // Get a sibling node on current level: this is proof[h]\n                root_ = getParent(root_, proof[h], index, h);\n            }\n            // Go up to the root: the remaining siblings are EMPTY\n            for (uint256 h = proofLen; h \u003c height; ++h) {\n                root_ = getParent(root_, bytes32(0), index, h);\n            }\n        }\n    }\n\n    /**\n     * @notice Calculates the parent of a node on the path from one of the leafs to root.\n     * @param node          Node on a path from tree leaf to root\n     * @param sibling       Sibling for a given node\n     * @param leafIndex     Index of the tree leaf\n     * @param nodeHeight    \"Level height\" for `node` (ZERO for leafs, ORIGIN_TREE_HEIGHT for root)\n     */\n    function getParent(bytes32 node, bytes32 sibling, uint256 leafIndex, uint256 nodeHeight)\n        internal\n        pure\n        returns (bytes32 parent)\n    {\n        // Index for `node` on its \"tree level\" is (leafIndex / 2**height)\n        // \"Left child\" has even index, \"right child\" has odd index\n        if ((leafIndex \u003e\u003e nodeHeight) \u0026 1 == 0) {\n            // Left child\n            return getParent(node, sibling);\n        } else {\n            // Right child\n            return getParent(sibling, node);\n        }\n    }\n\n    /// @notice Calculates the parent of tow nodes in the merkle tree.\n    /// @dev We use implementation with H(0,0) = 0\n    /// This makes EVERY empty node in the tree equal to ZERO,\n    /// saving us from storing H(0,0), H(H(0,0), H(0, 0)), and so on\n    /// @param leftChild    Left child of the calculated node\n    /// @param rightChild   Right child of the calculated node\n    /// @return parent      Value for the node having above mentioned children\n    function getParent(bytes32 leftChild, bytes32 rightChild) internal pure returns (bytes32 parent) {\n        if (leftChild == bytes32(0) \u0026\u0026 rightChild == bytes32(0)) {\n            return 0;\n        } else {\n            return keccak256(bytes.concat(leftChild, rightChild));\n        }\n    }\n\n    // ════════════════════════════════ ROOT/PROOF CALCULATION FOR A LIST OF LEAFS ═════════════════════════════════════\n\n    /**\n     * @notice Calculates merkle root for a list of given leafs.\n     * Merkle Tree is constructed by padding the list with ZERO values for leafs until list length is `2**height`.\n     * Merkle Root is calculated for the constructed tree, and then saved in `leafs[0]`.\n     * \u003e Note:\n     * \u003e - `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * \u003e - Caller is expected not to reuse `hashes` list after the call, and only use `leafs[0]` value,\n     * which is guaranteed to contain the calculated merkle root.\n     * \u003e - root is calculated using the `H(0,0) = 0` Merkle Tree implementation. See MerkleTree.sol for details.\n     * @dev Amount of leaves should be at most `2**height`\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param height    Height of the Merkle Tree to construct\n     */\n    function calculateRoot(bytes32[] memory hashes, uint256 height) internal pure {\n        uint256 levelLength = hashes.length;\n        // Amount of hashes could not exceed amount of leafs in tree with the given height\n        if (levelLength \u003e (1 \u003c\u003c height)) revert TreeHeightTooLow();\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\": the amount of iterations for the for loop above.\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n            }\n        }\n    }\n\n    /**\n     * @notice Generates a proof of inclusion of a leaf in the list. If the requested index is outside\n     * of the list range, generates a proof of inclusion for an empty leaf (proof of non-inclusion).\n     * The Merkle Tree is constructed by padding the list with ZERO values until list length is a power of two\n     * __AND__ index is in the extended list range. For example:\n     *  - `hashes.length == 6` and `0 \u003c= index \u003c= 7` will \"extend\" the list to 8 entries.\n     *  - `hashes.length == 6` and `7 \u003c index \u003c= 15` will \"extend\" the list to 16 entries.\n     * \u003e Note: `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * Caller is expected not to reuse `hashes` list after the call.\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param index     Leaf index to generate the proof for\n     * @return proof    Generated merkle proof\n     */\n    function calculateProof(bytes32[] memory hashes, uint256 index) internal pure returns (bytes32[] memory proof) {\n        // Use only meaningful values for the shortened proof\n        // Check if index is within the list range (we want to generates proofs for outside leafs as well)\n        uint256 height = getHeight(index \u003c hashes.length ? hashes.length : (index + 1));\n        proof = new bytes32[](height);\n        uint256 levelLength = hashes.length;\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Use sibling for the merkle proof; `index^1` is index of our sibling\n                proof[h] = (index ^ 1 \u003c levelLength) ? hashes[index ^ 1] : bytes32(0);\n\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\"\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n                // Traverse to parent node\n                index \u003e\u003e= 1;\n            }\n        }\n    }\n\n    /// @notice Returns the height of the tree having a given amount of leafs.\n    function getHeight(uint256 leafs) internal pure returns (uint256 height) {\n        uint256 amount = 1;\n        while (amount \u003c leafs) {\n            unchecked {\n                ++height;\n            }\n            amount \u003c\u003c= 1;\n        }\n    }\n}\n\n// contracts/libs/stack/GasData.sol\n\n/// GasData in encoded data with \"basic information about gas prices\" for some chain.\ntype GasData is uint96;\n\nusing GasDataLib for GasData global;\n\n/// ChainGas is encoded data with given chain's \"basic information about gas prices\".\ntype ChainGas is uint128;\n\nusing GasDataLib for ChainGas global;\n\n/// Library for encoding and decoding GasData and ChainGas structs.\n/// # GasData\n/// `GasData` is a struct to store the \"basic information about gas prices\", that could\n/// be later used to approximate the cost of a message execution, and thus derive the\n/// minimal tip values for sending a message to the chain.\n/// \u003e - `GasData` is supposed to be cached by `GasOracle` contract, allowing to store the\n/// \u003e approximates instead of the exact values, and thus save on storage costs.\n/// \u003e - For instance, if `GasOracle` only updates the values on +- 10% change, having an\n/// \u003e 0.4% error on the approximates would be acceptable.\n/// `GasData` is supposed to be included in the Origin's state, which are synced across\n/// chains using Agent-signed snapshots and attestations.\n/// ## GasData stack layout (from highest bits to lowest)\n///\n/// | Position   | Field        | Type   | Bytes | Description                                         |\n/// | ---------- | ------------ | ------ | ----- | --------------------------------------------------- |\n/// | (012..010] | gasPrice     | uint16 | 2     | Gas price for the chain (in Wei per gas unit)       |\n/// | (010..008] | dataPrice    | uint16 | 2     | Calldata price (in Wei per byte of content)         |\n/// | (008..006] | execBuffer   | uint16 | 2     | Tx fee safety buffer for message execution (in Wei) |\n/// | (006..004] | amortAttCost | uint16 | 2     | Amortized cost for attestation submission (in Wei)  |\n/// | (004..002] | etherPrice   | uint16 | 2     | Chain's Ether Price / Mainnet Ether Price (in BWAD) |\n/// | (002..000] | markup       | uint16 | 2     | Markup for the message execution (in BWAD)          |\n/// \u003e See Number.sol for more details on `Number` type and BWAD (binary WAD) math.\n///\n/// ## ChainGas stack layout (from highest bits to lowest)\n///\n/// | Position   | Field   | Type   | Bytes | Description      |\n/// | ---------- | ------- | ------ | ----- | ---------------- |\n/// | (016..004] | gasData | uint96 | 12    | Chain's gas data |\n/// | (004..000] | domain  | uint32 | 4     | Chain's domain   |\nlibrary GasDataLib {\n    /// @dev Amount of bits to shift to gasPrice field\n    uint96 private constant SHIFT_GAS_PRICE = 10 * 8;\n    /// @dev Amount of bits to shift to dataPrice field\n    uint96 private constant SHIFT_DATA_PRICE = 8 * 8;\n    /// @dev Amount of bits to shift to execBuffer field\n    uint96 private constant SHIFT_EXEC_BUFFER = 6 * 8;\n    /// @dev Amount of bits to shift to amortAttCost field\n    uint96 private constant SHIFT_AMORT_ATT_COST = 4 * 8;\n    /// @dev Amount of bits to shift to etherPrice field\n    uint96 private constant SHIFT_ETHER_PRICE = 2 * 8;\n\n    /// @dev Amount of bits to shift to gasData field\n    uint128 private constant SHIFT_GAS_DATA = 4 * 8;\n\n    // ═════════════════════════════════════════════════ GAS DATA ══════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded GasData struct with the given fields.\n    /// @param gasPrice_        Gas price for the chain (in Wei per gas unit)\n    /// @param dataPrice_       Calldata price (in Wei per byte of content)\n    /// @param execBuffer_      Tx fee safety buffer for message execution (in Wei)\n    /// @param amortAttCost_    Amortized cost for attestation submission (in Wei)\n    /// @param etherPrice_      Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n    /// @param markup_          Markup for the message execution (in BWAD)\n    function encodeGasData(\n        Number gasPrice_,\n        Number dataPrice_,\n        Number execBuffer_,\n        Number amortAttCost_,\n        Number etherPrice_,\n        Number markup_\n    ) internal pure returns (GasData) {\n        // Number type wraps uint16, so could safely be casted to uint96\n        // forgefmt: disable-next-item\n        return GasData.wrap(\n            uint96(Number.unwrap(gasPrice_)) \u003c\u003c SHIFT_GAS_PRICE |\n            uint96(Number.unwrap(dataPrice_)) \u003c\u003c SHIFT_DATA_PRICE |\n            uint96(Number.unwrap(execBuffer_)) \u003c\u003c SHIFT_EXEC_BUFFER |\n            uint96(Number.unwrap(amortAttCost_)) \u003c\u003c SHIFT_AMORT_ATT_COST |\n            uint96(Number.unwrap(etherPrice_)) \u003c\u003c SHIFT_ETHER_PRICE |\n            uint96(Number.unwrap(markup_))\n        );\n    }\n\n    /// @notice Wraps padded uint256 value into GasData struct.\n    function wrapGasData(uint256 paddedGasData) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(paddedGasData));\n    }\n\n    /// @notice Returns the gas price, in Wei per gas unit.\n    function gasPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_GAS_PRICE));\n    }\n\n    /// @notice Returns the calldata price, in Wei per byte of content.\n    function dataPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_DATA_PRICE));\n    }\n\n    /// @notice Returns the tx fee safety buffer for message execution, in Wei.\n    function execBuffer(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_EXEC_BUFFER));\n    }\n\n    /// @notice Returns the amortized cost for attestation submission, in Wei.\n    function amortAttCost(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_AMORT_ATT_COST));\n    }\n\n    /// @notice Returns the ratio of Chain's Ether Price / Mainnet Ether Price, in BWAD math.\n    function etherPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_ETHER_PRICE));\n    }\n\n    /// @notice Returns the markup for the message execution, in BWAD math.\n    function markup(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data)));\n    }\n\n    // ════════════════════════════════════════════════ CHAIN DATA ═════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded ChainGas struct with the given fields.\n    /// @param gasData_ Chain's gas data\n    /// @param domain_  Chain's domain\n    function encodeChainGas(GasData gasData_, uint32 domain_) internal pure returns (ChainGas) {\n        // GasData type wraps uint96, so could safely be casted to uint128\n        return ChainGas.wrap(uint128(GasData.unwrap(gasData_)) \u003c\u003c SHIFT_GAS_DATA | uint128(domain_));\n    }\n\n    /// @notice Wraps padded uint256 value into ChainGas struct.\n    function wrapChainGas(uint256 paddedChainGas) internal pure returns (ChainGas) {\n        // Casting to uint128 will truncate the highest bits, which is the behavior we want\n        return ChainGas.wrap(uint128(paddedChainGas));\n    }\n\n    /// @notice Returns the chain's gas data.\n    function gasData(ChainGas data) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(ChainGas.unwrap(data) \u003e\u003e SHIFT_GAS_DATA));\n    }\n\n    /// @notice Returns the chain's domain.\n    function domain(ChainGas data) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(ChainGas.unwrap(data));\n    }\n\n    /// @notice Returns the hash for the list of ChainGas structs.\n    function snapGasHash(ChainGas[] memory snapGas) internal pure returns (bytes32 snapGasHash_) {\n        // Use assembly to calculate the hash of the array without copying it\n        // ChainGas takes a single word of storage, thus ChainGas[] is stored in the following way:\n        // 0x00: length of the array, in words\n        // 0x20: first ChainGas struct\n        // 0x40: second ChainGas struct\n        // And so on...\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Find the location where the array data starts, we add 0x20 to skip the length field\n            let loc := add(snapGas, 0x20)\n            // Load the length of the array (in words).\n            // Shifting left 5 bits is equivalent to multiplying by 32: this converts from words to bytes.\n            let len := shl(5, mload(snapGas))\n            // Calculate the hash of the array\n            snapGasHash_ := keccak256(loc, len)\n        }\n    }\n}\n\n// contracts/libs/stack/Header.sol\n\n/// Header is encoded data with \"general routing information\".\ntype Header is uint136;\n\nusing HeaderLib for Header global;\n\n/// Types of messages supported by Origin-Destination\n/// - Base: message sent by protocol user, contains tips\n/// - Manager: message sent between AgentManager contracts located on different chains, no tips\nenum MessageFlag {\n    Base,\n    Manager\n}\n\nusing HeaderLib for MessageFlag global;\n\n/// Library for formatting _the header part_ of _the messages used by Origin and Destination_.\n/// - Header represents general information for routing a Message for Origin and Destination.\n/// - Header occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n///\n/// # Header stack layout (from highest bits to lowest)\n///\n/// | Position   | Field            | Type   | Bytes | Description                             |\n/// | ---------- | ---------------- | ------ | ----- | --------------------------------------- |\n/// | (017..016] | flag             | uint8  | 1     | Flag specifying the type of message     |\n/// | (016..012] | origin           | uint32 | 4     | Domain where message originated         |\n/// | (012..008] | nonce            | uint32 | 4     | Message nonce on the origin domain      |\n/// | (008..004] | destination      | uint32 | 4     | Domain where message will be executed   |\n/// | (004..000] | optimisticPeriod | uint32 | 4     | Optimistic period that will be enforced |\nlibrary HeaderLib {\n    /// @dev Amount of bits to shift to flag field\n    uint136 private constant SHIFT_FLAG = 16 * 8;\n    /// @dev Amount of bits to shift to origin field\n    uint136 private constant SHIFT_ORIGIN = 12 * 8;\n    /// @dev Amount of bits to shift to nonce field\n    uint136 private constant SHIFT_NONCE = 8 * 8;\n    /// @dev Amount of bits to shift to destination field\n    uint136 private constant SHIFT_DESTINATION = 4 * 8;\n\n    /// @notice Returns an encoded header with provided fields\n    /// @param origin_              Domain of origin chain\n    /// @param nonce_               Message nonce on origin chain\n    /// @param destination_         Domain of destination chain\n    /// @param optimisticPeriod_    Optimistic period for message execution\n    function encodeHeader(\n        MessageFlag flag_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint32 destination_,\n        uint32 optimisticPeriod_\n    ) internal pure returns (Header) {\n        // All casts below are upcasts, so they are safe\n        // forgefmt: disable-next-item\n        return Header.wrap(\n            uint136(uint8(flag_)) \u003c\u003c SHIFT_FLAG |\n            uint136(origin_) \u003c\u003c SHIFT_ORIGIN |\n            uint136(nonce_) \u003c\u003c SHIFT_NONCE |\n            uint136(destination_) \u003c\u003c SHIFT_DESTINATION |\n            uint136(optimisticPeriod_)\n        );\n    }\n\n    /// @notice Checks that the header is a valid encoded header.\n    function isHeader(uint256 paddedHeader) internal pure returns (bool) {\n        // Check that flag is within range\n        return _flag(paddedHeader) \u003c= uint8(type(MessageFlag).max);\n    }\n\n    /// @notice Wraps the padded encoded request into a Header-typed value.\n    /// @dev The \"padded\" header is simply an encoded header casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded headers\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedHeader) internal pure returns (Header) {\n        // Check that flag is within range\n        if (!isHeader(paddedHeader)) revert FlagOutOfRange();\n        // Casting to uint136 will truncate the highest bits, which is the behavior we want\n        return Header.wrap(uint136(paddedHeader));\n    }\n\n    /// @notice Returns header's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Header header) internal pure returns (bytes32 hashedHeader) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store header in scratch space\n            mstore(0, header)\n            // Compute hash of header padded to 32 bytes\n            hashedHeader := keccak256(0, 32)\n        }\n    }\n\n    // ══════════════════════════════════════════════ HEADER SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns header's flag field\n    function flag(Header header) internal pure returns (MessageFlag) {\n        // We check that flag is within range when wrapping the header, so this cast is safe\n        return MessageFlag(_flag(Header.unwrap(header)));\n    }\n\n    /// @notice Returns header's origin field\n    function origin(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_ORIGIN);\n    }\n\n    /// @notice Returns header's nonce field\n    function nonce(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_NONCE);\n    }\n\n    /// @notice Returns header's destination field\n    function destination(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_DESTINATION);\n    }\n\n    /// @notice Returns header's optimistic seconds field\n    function optimisticPeriod(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns header's flag field without casting to MessageFlag\n    function _flag(uint256 paddedHeader) private pure returns (uint8) {\n        // Casting to uint8 will truncate the highest bits, which is the behavior we want\n        return uint8(paddedHeader \u003e\u003e SHIFT_FLAG);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n     * constructor.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall \u0026\u0026 _initialized \u003c 1) || (!AddressUpgradeable.isContract(address(this)) \u0026\u0026 _initialized == 1),\n            \"Initializable: contract is already initialized\"\n        );\n        _initialized = 1;\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: setting the version to 255 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing \u0026\u0026 _initialized \u003c version, \"Initializable: contract is already initialized\");\n        _initialized = version;\n        _initializing = true;\n        _;\n        _initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        require(_initializing, \"Initializable: contract is not initializing\");\n        _;\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized != type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint8) {\n        return _initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _initializing;\n    }\n}\n\n// contracts/interfaces/IAgentManager.sol\n\ninterface IAgentManager {\n    /**\n     * @notice Allows Inbox to open a Dispute between a Guard and a Notary, if they are both not in Dispute already.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Guard or Notary is already in Dispute.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Allows Inbox to slash an agent, if their fraud was proven.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Domain doesn't match the saved agent domain.\n     * @param domain    Domain where the Agent is active\n     * @param agent     Address of the Agent\n     * @param prover    Address that initially provided fraud proof\n     */\n    function slashAgent(uint32 domain, address agent, address prover) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest known root of the Agent Merkle Tree.\n     */\n    function agentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns the number of opened Disputes.\n     * @dev This includes the Disputes that have been resolved already.\n     */\n    function getDisputesAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns information about the dispute with the given index.\n     * @dev Will revert if dispute with given index hasn't been opened yet.\n     * @param index             Dispute index\n     * @return guard            Address of the Guard in the Dispute\n     * @return notary           Address of the Notary in the Dispute\n     * @return slashedAgent     Address of the Agent who was slashed when Dispute was resolved\n     * @return fraudProver      Address who provided fraud proof to resolve the Dispute\n     * @return reportPayload    Raw payload with report data that led to the Dispute\n     * @return reportSignature  Guard signature for the report payload\n     */\n    function getDispute(uint256 index)\n        external\n        view\n        returns (\n            address guard,\n            address notary,\n            address slashedAgent,\n            address fraudProver,\n            bytes memory reportPayload,\n            bytes memory reportSignature\n        );\n\n    /**\n     * @notice Returns the current Dispute status of a given agent. See Structures.sol for details.\n     * @dev Every returned value will be set to zero if agent was not slashed and is not in Dispute.\n     * `rival` and `disputePtr` will be set to zero if the agent was slashed without being in Dispute.\n     * @param agent         Agent address\n     * @return flag         Flag describing the current Dispute status for the agent: None/Pending/Slashed\n     * @return rival        Address of the rival agent in the Dispute\n     * @return fraudProver  Address who provided fraud proof to resolve the Dispute\n     * @return disputePtr   Index of the opened Dispute PLUS ONE. Zero if agent is not in Dispute.\n     */\n    function disputeStatus(address agent)\n        external\n        view\n        returns (DisputeFlag flag, address rival, address fraudProver, uint256 disputePtr);\n}\n\n// contracts/interfaces/IAgentSecured.sol\n\ninterface IAgentSecured {\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * between a Guard and a Notary has been opened.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * has been resolved due to one of the agents being slashed.\n     * \u003e `rivalIndex` will be ZERO, if the slashed agent was not in the Dispute.\n     * @param slashedIndex  Index of the slashed agent in the Agent Merkle Tree\n     * @param rivalIndex    Index of the their Dispute Rival in the Agent Merkle Tree\n     */\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the address of the local AgentManager contract, which is treated as\n     * the \"source of truth\" for agent statuses.\n     */\n    function agentManager() external view returns (address);\n\n    /**\n     * @notice Returns the address of the local Inbox contract, which is treated as\n     * the \"source of truth\" for agent-signed statements.\n     * @dev Inbox passes verified agent statements to `IAgentSecured` contract.\n     */\n    function inbox() external view returns (address);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns (flag, openedAt, resolvedAt) that describes the latest status of\n     * the latest dispute for an agent with a given index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param agentIndex    Agent index in the Agent Merkle Tree\n     * @return              Latest dispute status for the given agent: (flag, openedAt, resolvedAt)\n     */\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory);\n}\n\n// contracts/libs/memory/ByteString.sol\n\n/// @dev CallData is a memory view over the payload to be used for an external call, i.e.\n/// recipient.call(callData). Its length is always (4 + 32 * N) bytes:\n/// - First 4 bytes represent the function selector.\n/// - 32 * N bytes represent N words that function arguments occupy.\ntype CallData is uint256;\n\n/// @dev Attach library functions to CallData\nusing ByteString for CallData global;\n\n/// @dev Signature is a memory view over a \"65 bytes\" array representing a ECDSA signature.\ntype Signature is uint256;\n\n/// @dev Attach library functions to Signature\nusing ByteString for Signature global;\n\nlibrary ByteString {\n    using MemViewLib for bytes;\n\n    /**\n     * @dev non-compact ECDSA signatures are enforced as of OZ 4.7.3\n     *\n     *      Signature payload memory layout\n     * [000 .. 032) r   bytes32 32 bytes\n     * [032 .. 064) s   bytes32 32 bytes\n     * [064 .. 065) v   uint8    1 byte\n     */\n    uint256 internal constant SIGNATURE_LENGTH = 65;\n    uint256 private constant OFFSET_R = 0;\n    uint256 private constant OFFSET_S = 32;\n    uint256 private constant OFFSET_V = 64;\n\n    /**\n     * @dev Calldata memory layout\n     * [000 .. 004) selector    bytes4  4 bytes\n     *      Optional: N function arguments\n     * [004 .. 036) arg1        bytes32 32 bytes\n     *      ..\n     * [AAA .. END) argN        bytes32 32 bytes\n     */\n    uint256 internal constant SELECTOR_LENGTH = 4;\n    uint256 private constant OFFSET_SELECTOR = 0;\n    uint256 private constant OFFSET_ARGUMENTS = SELECTOR_LENGTH;\n\n    // ═════════════════════════════════════════════════ SIGNATURE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the signature payload from the given values.\n     * @dev Using ByteString.formatSignature({r: r, s: s, v: v}) will make sure\n     * that params are given in the right order.\n     */\n    function formatSignature(bytes32 r, bytes32 s, uint8 v) internal pure returns (bytes memory) {\n        return abi.encodePacked(r, s, v);\n    }\n\n    /**\n     * @notice Returns a Signature view over for the given payload.\n     * @dev Will revert if the payload is not a signature.\n     */\n    function castToSignature(bytes memory payload) internal pure returns (Signature) {\n        return castToSignature(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Signature view.\n     * @dev Will revert if the memory view is not over a signature.\n     */\n    function castToSignature(MemView memView) internal pure returns (Signature) {\n        if (!isSignature(memView)) revert UnformattedSignature();\n        return Signature.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a signature\n     */\n    function isSignature(MemView memView) internal pure returns (bool) {\n        return memView.len() == SIGNATURE_LENGTH;\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Signature signature) internal pure returns (MemView) {\n        return MemView.wrap(Signature.unwrap(signature));\n    }\n\n    // ═════════════════════════════════════════════ SIGNATURE SLICING ═════════════════════════════════════════════════\n\n    /// @notice Unpacks signature payload into (r, s, v) parameters.\n    /// @dev Make sure to verify signature length with isSignature() beforehand.\n    function toRSV(Signature signature) internal pure returns (bytes32 r, bytes32 s, uint8 v) {\n        // Get the underlying memory view\n        MemView memView = unwrap(signature);\n        r = memView.index({index_: OFFSET_R, bytes_: 32});\n        s = memView.index({index_: OFFSET_S, bytes_: 32});\n        // Can be safely casted to uint8, since we index a single byte\n        v = uint8(memView.indexUint({index_: OFFSET_V, bytes_: 1}));\n    }\n\n    // ═════════════════════════════════════════════════ CALLDATA ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the calldata with the modified arguments:\n     * the existing arguments are prepended with the arguments from the prefix.\n     * @dev Given:\n     *  - `calldata = abi.encodeWithSelector(foo.selector, d, e);`\n     *  - `prefix = abi.encode(a, b, c);`\n     *  - `a`, `b`, `c` are arguments of static type (i.e. not dynamically sized ones)\n     *      Then:\n     *  - Function will return abi.encodeWithSelector(foo.selector, a, c, c, d, e)\n     *  - Returned calldata will trigger `foo(a, b, c, d, e)` when used for a contract call.\n     * Note: for clarification as to what types are considered static, see\n     * https://docs.soliditylang.org/en/latest/abi-spec.html#formal-specification-of-the-encoding\n     * @param callData  Calldata that needs to be modified\n     * @param prefix    ABI-encoded arguments to use as the first arguments in the new calldata\n     * @return Modified calldata having prefix as the first arguments.\n     */\n    function addPrefix(CallData callData, bytes memory prefix) internal view returns (bytes memory) {\n        // Prefix should occupy a whole amount of words in memory\n        if (!_fullWords(prefix.length)) revert UnformattedCallDataPrefix();\n        MemView[] memory views = new MemView[](3);\n        // Use payload's function selector\n        views[0] = abi.encodePacked(callData.callSelector()).ref();\n        // Use prefix as the first arguments\n        views[1] = prefix.ref();\n        // Use payload's remaining arguments\n        views[2] = callData.arguments();\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a CallData view over for the given payload.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(bytes memory payload) internal pure returns (CallData) {\n        return castToCallData(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a CallData view.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(MemView memView) internal pure returns (CallData) {\n        if (!isCallData(memView)) revert UnformattedCallData();\n        return CallData.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a valid calldata, i.e.\n     * a function selector, followed by arbitrary amount of arguments.\n     */\n    function isCallData(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Calldata should at least have a function selector\n        if (length \u003c SELECTOR_LENGTH) return false;\n        // The remainder of the calldata should be exactly N memory words (N \u003e= 0)\n        return _fullWords(length - SELECTOR_LENGTH);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(CallData callData) internal pure returns (MemView) {\n        return MemView.wrap(CallData.unwrap(callData));\n    }\n\n    /// @notice Returns callData's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(CallData callData) internal pure returns (bytes32) {\n        return callData.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ CALLDATA SLICING ══════════════════════════════════════════════════\n\n    /**\n     * @notice Returns amount of memory words (32 byte chunks) the function arguments\n     * occupy in the calldata.\n     * @dev This might differ from amount of arguments supplied, if any of the arguments\n     * occupies more than one memory slot. It is true, however, that argument part of the payload\n     * occupies exactly N words, even for dynamic types like `bytes`\n     */\n    function argumentWords(CallData callData) internal pure returns (uint256) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        // Equivalent of (length - SELECTOR_LENGTH) / 32\n        return (memView.len() - SELECTOR_LENGTH) \u003e\u003e 5;\n    }\n\n    /// @notice Returns selector for the provided calldata.\n    function callSelector(CallData callData) internal pure returns (bytes4) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return bytes4(memView.index({index_: OFFSET_SELECTOR, bytes_: SELECTOR_LENGTH}));\n    }\n\n    /// @notice Returns abi encoded arguments for the provided calldata.\n    function arguments(CallData callData) internal pure returns (MemView) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return memView.sliceFrom({index_: OFFSET_ARGUMENTS});\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if length is full amount of memory words (32 bytes).\n    function _fullWords(uint256 length) internal pure returns (bool) {\n        // The equivalent of length % 32 == 0\n        return length \u0026 31 == 0;\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n    function __Context_init() internal onlyInitializing {\n    }\n\n    function __Context_init_unchained() internal onlyInitializing {\n    }\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[50] private __gap;\n}\n\n// contracts/libs/merkle/MerkleTree.sol\n\n/// `BaseTree` is a struct representing incremental merkle tree.\n/// - Contains only the current branch.\n/// - The number of inserted leaves is stored externally, and is later supplied for tree operations.\n/// - Has a fixed height of `ORIGIN_TREE_HEIGHT`.\n/// - Can store up to `2 ** ORIGIN_TREE_HEIGHT - 1` leaves.\n/// \u003e Note: the hash function for the tree `H(x, y)` is defined as:\n/// \u003e - `H(0,0) = 0`\n/// \u003e - `H(x,y) = keccak256(x, y), when (x != 0 || y != 0)`\n/// ## Invariant for leafs\n/// - The leftmost empty leaf has `index == count`, where `count` is the amount of the inserted leafs so far.\n/// - Value for any empty leaf or node is bytes32(0).\n/// ## Invariant for current branch\n/// `branch[i]` is always the value of a node on the i-th level.\n/// Levels are numbered from leafs to root: `0 .. ORIGIN_TREE_HEIGHT`.\n/// `branch[i]` stores the value for the node, such that:\n//  - The node is a \"left child\" (e.g. has an even index).\n/// - The node must have two non-empty children.\n/// - Out of all level's \"left child\" nodes with \"non-empty children\",\n/// the one with the biggest index (the rightmost one) is stored as `branch[i]`.\n/// \u003e __`branch` could be used to form a proof of inclusion for the first empty leaf (`index == count`).__\n/// _Here is how:_\n/// - Let's walk along the path from the \"first empty leaf\" to the root.\n/// - i-th bit of the \"first empty leaf\" index (which is equal to `count`) determines if the path's node\n/// for this i-th level is a \"left child\" or a \"right child\".\n/// - i-th bit in `count` is 0 → we are the left child on this level → sibling is the right child\n/// that does not exist yet → `proof[i] = bytes32(0)`.\n/// - i-th bit in `count` is 1 → we are the right child on this level → sibling is the left child\n/// sibling is the rightmost \"left child\" node on the level → `proof[i] = branch[i]`.\n/// \u003e Therefore `proof[i] = (count \u0026 (1 \u003c\u003c i)) == 0 ? bytes32(0) : branch[i])`\nstruct BaseTree {\n    bytes32[ORIGIN_TREE_HEIGHT] branch;\n}\n\nusing MerkleTree for BaseTree global;\n\n/// `HistoricalTree` is an incremental merkle tree keeping track of its historical merkle roots.\n/// \u003e - `roots[N]` is the root of the tree after `N` leafs were inserted\n/// \u003e - `roots[0] == bytes32(0)`\n/// @param tree     Incremental merkle tree\n/// @param roots    Historical merkle roots of the tree\nstruct HistoricalTree {\n    BaseTree tree;\n    bytes32[] roots;\n}\n\nusing MerkleTree for HistoricalTree global;\n\n/// `DynamicTree` is a struct representing a Merkle Tree with `2**AGENT_TREE_HEIGHT` leaves.\n/// - A single operation is available: update value for leaf with an arbitrary index (which might be a non-empty leaf).\n/// - This is done by requesting the proof of inclusion for the old value, which is used to both\n/// verify the old value, and calculate the new root.\n/// \u003e Based on Original idea from [ER forum post](https://ethresear.ch/t/efficient-on-chain-dynamic-merkle-tree/11054).\nstruct DynamicTree {\n    bytes32 root;\n}\n\nusing MerkleTree for DynamicTree global;\n\n/// MerkleTree is work based on Nomad's Merkle.sol, which is used under MIT OR Apache-2.0\n/// [link](https://github.com/nomad-xyz/monorepo/blob/main/packages/contracts-core/contracts/libs/Merkle.sol).\n/// With the following changes:\n/// - Adapted for Solidity 0.8.x.\n/// - Amount of tree leaves stored externally.\n/// - Added thorough documentation.\n/// - `H(0,0) = 0` optimization from [ER forum post](https://ethresear.ch/t/optimizing-sparse-merkle-trees/3751/6).\n/// \u003e Nomad's Merkle.sol is work based on eth2 deposit contract, which is used under CC0-1.0\n///[link](https://github.com/ethereum/deposit_contract/blob/dev/deposit_contract/contracts/validator_registration.v.py).\n/// With the following changes:\n/// \u003e - Implemented in Solidity 0.7.6 (eth2 deposit contract implemented in Vyper).\n/// \u003e - `H() = keccak256()` is used as the hashing function instead of `sha256()`.\nlibrary MerkleTree {\n    /// @dev For root calculation we need at least one empty leaf, thus the minus one in the formula.\n    uint256 internal constant MAX_LEAVES = 2 ** ORIGIN_TREE_HEIGHT - 1;\n\n    // ═════════════════════════════════════════════════ BASE TREE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Inserts `node` into merkle tree\n     * @dev Reverts if tree is full\n     * @param newCount  Amount of inserted leaves in the tree after the insertion (i.e. current + 1)\n     * @param node      Element to insert into tree\n     */\n    function insertBase(BaseTree storage tree, uint256 newCount, bytes32 node) internal {\n        if (newCount \u003e MAX_LEAVES) revert MerkleTreeFull();\n        // We go up the tree following the branch from the empty leaf AFTER the just inserted one.\n        // We stop when we find the first \"right child\" node.\n        // Its sibling is now the rightmost \"left child\" node that has two non-empty children.\n        // Therefore we need to update `tree.branch` value on this level.\n        // One could see that `tree.branch` value on lower and higher levels remain unchanged.\n\n        // Loop invariant: `node` is the current level's value for the branch from JUST INSERTED leaf\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            if ((newCount \u0026 1) == 1) {\n                // Found the first \"right child\" node on the branch from EMPTY leaf\n                // `node` is the value for node on branch from JUST INSERTED leaf\n                // Which in this case is the \"left child\".\n                // We update tree.branch and exit\n                tree.branch[i] = node;\n                return;\n            }\n            // On the branch from EMPTY leaf this is still a \"left child\".\n            // Meaning on branch from JUST INSERTED leaf, `node` is a right child.\n            // We compute value for `node` parent using `tree.branch` invariant:\n            // This is the rightmost \"left child\" node, which would be sibling of `node`.\n            node = MerkleMath.getParent(tree.branch[i], node);\n            // Get the parent index, and go to the next tree level\n            newCount \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n        // As the loop should always end prematurely with the `return` statement,\n        // this code should be unreachable. We assert `false` just to be safe.\n        assert(false);\n    }\n\n    /**\n     * @notice Calculates and returns current root of the merkle tree.\n     * @param count     Current amount of inserted leaves in the tree\n     * @return current  Calculated root of `tree`\n     */\n    function rootBase(BaseTree storage tree, uint256 count) internal view returns (bytes32 current) {\n        // To calculate the root we follow the branch of first EMPTY leaf (index == count)\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            // Check if we are the left or the right child on the current level\n            if ((count \u0026 1) == 1) {\n                // We are the right child. Our sibling is the \"rightmost\" \"left-child\" node\n                // that has two non-empty children → sibling is `tree.branch[i]`\n                current = MerkleMath.getParent(tree.branch[i], current);\n            } else {\n                // We are the left child. Our sibling does not exist yet → sibling is EMPTY\n                current = MerkleMath.getParent(current, bytes32(0));\n            }\n            // Get the parent index, and go to the next tree level\n            count \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    // ══════════════════════════════════════════════ HISTORICAL TREE ══════════════════════════════════════════════════\n\n    /// @notice Initializes the historical roots for the tree by inserting an empty root.\n    // solhint-disable-next-line ordering\n    function initializeRoots(HistoricalTree storage tree) internal returns (bytes32 savedRoot) {\n        // This should only be called once, when the contract is initialized\n        assert(tree.roots.length == 0);\n        // Save root for empty merkle tree: bytes32(0)\n        tree.roots.push(savedRoot);\n    }\n\n    /// @notice Inserts a new leaf into the merkle tree.\n    /// @dev Reverts if tree is full.\n    /// @param node         Element to insert into tree\n    /// @return newRoot     Merkle root after the leaf was inserted\n    function insert(HistoricalTree storage tree, bytes32 node) internal returns (bytes32 newRoot) {\n        // Tree count after the new leaf will be inserted (we store roots[0] as root of empty tree)\n        uint256 newCount = tree.roots.length;\n        tree.tree.insertBase(newCount, node);\n        // Save the new root\n        newRoot = tree.tree.rootBase(newCount);\n        tree.roots.push(newRoot);\n    }\n\n    /// @notice Returns the historical root of the merkle tree.\n    /// @dev Reverts if not enough leafs have been inserted.\n    /// @param count            Amount of leafs in the tree at some point of time\n    /// @return historicalRoot  Merkle root after `count` leafs were inserted\n    function root(HistoricalTree storage tree, uint256 count) internal view returns (bytes32 historicalRoot) {\n        if (count \u003e= tree.roots.length) revert NotEnoughLeafs();\n        return tree.roots[count];\n    }\n\n    // ═══════════════════════════════════════════════ DYNAMIC TREE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Updates the value for the leaf with the given index in the Dynamic Merkle Tree.\n     * @dev Will revert if incorrect proof of inclusion for old value is supplied.\n     * @param tree          Dynamic merkle tree\n     * @param index         Index of the leaf to update\n     * @param oldValue      Previous value of the leaf\n     * @param branch        Proof of inclusion of previous value into the tree\n     * @param newValue      New leaf value to assign\n     * @return newRoot      New value for the Merkle Root after the leaf is updated\n     */\n    function update(\n        DynamicTree storage tree,\n        uint256 index,\n        bytes32 oldValue,\n        bytes32[] memory branch,\n        bytes32 newValue\n    ) internal returns (bytes32 newRoot) {\n        // Check that the old value + proof result in a correct root\n        if (MerkleMath.proofRoot(index, oldValue, branch, AGENT_TREE_HEIGHT) != tree.root) {\n            revert LeafNotProven();\n        }\n        // New root is new value + the same proof (values for sibling nodes are not updated)\n        newRoot = MerkleMath.proofRoot(index, newValue, branch, AGENT_TREE_HEIGHT);\n        // Write the new root\n        tree.root = newRoot;\n    }\n}\n\n// contracts/libs/stack/Tips.sol\n\n/// Tips is encoded data with \"tips paid for sending a base message\".\n/// Note: even though uint256 is also an underlying type for MemView, Tips is stored ON STACK.\ntype Tips is uint256;\n\nusing TipsLib for Tips global;\n\n/// # Tips\n/// Library for formatting _the tips part_ of _the base messages_.\n///\n/// ## How the tips are awarded\n/// Tips are paid for sending a base message, and are split across all the agents that\n/// made the message execution on destination chain possible.\n/// ### Summit tips\n/// Split between:\n///     - Guard posting a snapshot with state ST_G for the origin chain.\n///     - Notary posting a snapshot SN_N using ST_G. This creates attestation A.\n///     - Notary posting a message receipt after it is executed on destination chain.\n/// ### Attestation tips\n/// Paid to:\n///     - Notary posting attestation A to destination chain.\n/// ### Execution tips\n/// Paid to:\n///     - First executor performing a valid execution attempt (correct proofs, optimistic period over),\n///      using attestation A to prove message inclusion on origin chain, whether the recipient reverted or not.\n/// ### Delivery tips.\n/// Paid to:\n///     - Executor who successfully executed the message on destination chain.\n///\n/// ## Tips encoding\n/// - Tips occupy a single storage word, and thus are stored on stack instead of being stored in memory.\n/// - The actual tip values should be determined by multiplying stored values by divided by TIPS_MULTIPLIER=2**32.\n/// - Tips are packed into a single word of storage, while allowing real values up to ~8*10**28 for every tip category.\n/// \u003e The only downside is that the \"real tip values\" are now multiplies of ~4*10**9, which should be fine even for\n/// the chains with the most expensive gas currency.\n/// # Tips stack layout (from highest bits to lowest)\n///\n/// | Position   | Field          | Type   | Bytes | Description                                                |\n/// | ---------- | -------------- | ------ | ----- | ---------------------------------------------------------- |\n/// | (032..024] | summitTip      | uint64 | 8     | Tip for agents interacting with Summit contract            |\n/// | (024..016] | attestationTip | uint64 | 8     | Tip for Notary posting attestation to Destination contract |\n/// | (016..008] | executionTip   | uint64 | 8     | Tip for valid execution attempt on destination chain       |\n/// | (008..000] | deliveryTip    | uint64 | 8     | Tip for successful message delivery on destination chain   |\n\nlibrary TipsLib {\n    using SafeCast for uint256;\n\n    /// @dev Amount of bits to shift to summitTip field\n    uint256 private constant SHIFT_SUMMIT_TIP = 24 * 8;\n    /// @dev Amount of bits to shift to attestationTip field\n    uint256 private constant SHIFT_ATTESTATION_TIP = 16 * 8;\n    /// @dev Amount of bits to shift to executionTip field\n    uint256 private constant SHIFT_EXECUTION_TIP = 8 * 8;\n\n    // ═══════════════════════════════════════════════════ TIPS ════════════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips with the given fields\n    /// @param summitTip_        Tip for agents interacting with Summit contract, divided by TIPS_MULTIPLIER\n    /// @param attestationTip_   Tip for Notary posting attestation to Destination contract, divided by TIPS_MULTIPLIER\n    /// @param executionTip_     Tip for valid execution attempt on destination chain, divided by TIPS_MULTIPLIER\n    /// @param deliveryTip_      Tip for successful message delivery on destination chain, divided by TIPS_MULTIPLIER\n    function encodeTips(uint64 summitTip_, uint64 attestationTip_, uint64 executionTip_, uint64 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // forgefmt: disable-next-item\n        return Tips.wrap(\n            uint256(summitTip_) \u003c\u003c SHIFT_SUMMIT_TIP |\n            uint256(attestationTip_) \u003c\u003c SHIFT_ATTESTATION_TIP |\n            uint256(executionTip_) \u003c\u003c SHIFT_EXECUTION_TIP |\n            uint256(deliveryTip_)\n        );\n    }\n\n    /// @notice Convenience function to encode tips with uint256 values.\n    function encodeTips256(uint256 summitTip_, uint256 attestationTip_, uint256 executionTip_, uint256 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // In practice, the tips amounts are not supposed to be higher than 2**96, and with 32 bits of granularity\n        // using uint64 is enough to store the values. However, we still check for overflow just in case.\n        // TODO: consider using Number type to store the tips values.\n        return encodeTips({\n            summitTip_: (summitTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            attestationTip_: (attestationTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            executionTip_: (executionTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            deliveryTip_: (deliveryTip_ \u003e\u003e TIPS_GRANULARITY).toUint64()\n        });\n    }\n\n    /// @notice Wraps the padded encoded tips into a Tips-typed value.\n    /// @dev There is no actual padding here, as the underlying type is already uint256,\n    /// but we include this function for consistency and to be future-proof, if tips will eventually use anything\n    /// smaller than uint256.\n    function wrapPadded(uint256 paddedTips) internal pure returns (Tips) {\n        return Tips.wrap(paddedTips);\n    }\n\n    /**\n     * @notice Returns a formatted Tips payload specifying empty tips.\n     * @return Formatted tips\n     */\n    function emptyTips() internal pure returns (Tips) {\n        return Tips.wrap(0);\n    }\n\n    /// @notice Returns tips's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Tips tips) internal pure returns (bytes32 hashedTips) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store tips in scratch space\n            mstore(0, tips)\n            // Compute hash of tips padded to 32 bytes\n            hashedTips := keccak256(0, 32)\n        }\n    }\n\n    // ═══════════════════════════════════════════════ TIPS SLICING ════════════════════════════════════════════════════\n\n    /// @notice Returns summitTip field\n    function summitTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_SUMMIT_TIP);\n    }\n\n    /// @notice Returns attestationTip field\n    function attestationTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_ATTESTATION_TIP);\n    }\n\n    /// @notice Returns executionTip field\n    function executionTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_EXECUTION_TIP);\n    }\n\n    /// @notice Returns deliveryTip field\n    function deliveryTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips));\n    }\n\n    // ════════════════════════════════════════════════ TIPS VALUE ═════════════════════════════════════════════════════\n\n    /// @notice Returns total value of the tips payload.\n    /// This is the sum of the encoded values, scaled up by TIPS_MULTIPLIER\n    function value(Tips tips) internal pure returns (uint256 value_) {\n        value_ = uint256(tips.summitTip()) + tips.attestationTip() + tips.executionTip() + tips.deliveryTip();\n        value_ \u003c\u003c= TIPS_GRANULARITY;\n    }\n\n    /// @notice Increases the delivery tip to match the new value.\n    function matchValue(Tips tips, uint256 newValue) internal pure returns (Tips newTips) {\n        uint256 oldValue = tips.value();\n        if (newValue \u003c oldValue) revert TipsValueTooLow();\n        // We want to increase the delivery tip, while keeping the other tips the same\n        unchecked {\n            uint256 delta = (newValue - oldValue) \u003e\u003e TIPS_GRANULARITY;\n            // `delta` fits into uint224, as TIPS_GRANULARITY is 32, so this never overflows uint256.\n            // In practice, this will never overflow uint64 as well, but we still check it just in case.\n            if (delta + tips.deliveryTip() \u003e type(uint64).max) revert TipsOverflow();\n            // Delivery tips occupy lowest 8 bytes, so we can just add delta to the tips value\n            // to effectively increase the delivery tip (knowing that delta fits into uint64).\n            newTips = Tips.wrap(Tips.unwrap(tips) + delta);\n        }\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    function __Ownable_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable_init_unchained() internal onlyInitializing {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n    function __Ownable2Step_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable2Step_init_unchained() internal onlyInitializing {\n    }\n    address private _pendingOwner;\n\n    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Returns the address of the pending owner.\n     */\n    function pendingOwner() public view virtual returns (address) {\n        return _pendingOwner;\n    }\n\n    /**\n     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual override onlyOwner {\n        _pendingOwner = newOwner;\n        emit OwnershipTransferStarted(owner(), newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual override {\n        delete _pendingOwner;\n        super._transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev The new owner accepts the ownership transfer.\n     */\n    function acceptOwnership() public virtual {\n        address sender = _msgSender();\n        require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n        _transferOwnership(sender);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// contracts/libs/memory/State.sol\n\n/// State is a memory view over a formatted state payload.\ntype State is uint256;\n\nusing StateLib for State global;\n\n/// # State\n/// State structure represents the state of Origin contract at some point of time.\n/// - State is structured in a way to track the updates of the Origin Merkle Tree.\n/// - State includes root of the Origin Merkle Tree, origin domain and some additional metadata.\n/// ## Origin Merkle Tree\n/// Hash of every sent message is inserted in the Origin Merkle Tree, which changes\n/// the value of Origin Merkle Root (which is the root for the mentioned tree).\n/// - Origin has a single Merkle Tree for all messages, regardless of their destination domain.\n/// - This leads to Origin state being updated if and only if a message was sent in a block.\n/// - Origin contract is a \"source of truth\" for states: a state is considered \"valid\" in its Origin,\n/// if it matches the state of the Origin contract after the N-th (nonce) message was sent.\n///\n/// # Memory layout of State fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                    |\n/// | ---------- | ----------- | ------- | ----- | ------------------------------ |\n/// | [000..032) | root        | bytes32 | 32    | Root of the Origin Merkle Tree |\n/// | [032..036) | origin      | uint32  | 4     | Domain where Origin is located |\n/// | [036..040) | nonce       | uint32  | 4     | Amount of sent messages        |\n/// | [040..045) | blockNumber | uint40  | 5     | Block of last sent message     |\n/// | [045..050) | timestamp   | uint40  | 5     | Time of last sent message      |\n/// | [050..062) | gasData     | uint96  | 12    | Gas data for the chain         |\n///\n/// @dev State could be used to form a Snapshot to be signed by a Guard or a Notary.\nlibrary StateLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_ROOT = 0;\n    uint256 private constant OFFSET_ORIGIN = 32;\n    uint256 private constant OFFSET_NONCE = 36;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 40;\n    uint256 private constant OFFSET_TIMESTAMP = 45;\n    uint256 private constant OFFSET_GAS_DATA = 50;\n\n    // ═══════════════════════════════════════════════════ STATE ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted State payload with provided fields\n     * @param root_         New merkle root\n     * @param origin_       Domain of Origin's chain\n     * @param nonce_        Nonce of the merkle root\n     * @param blockNumber_  Block number when root was saved in Origin\n     * @param timestamp_    Block timestamp when root was saved in Origin\n     * @param gasData_      Gas data for the chain\n     * @return Formatted state\n     */\n    function formatState(\n        bytes32 root_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_,\n        GasData gasData_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(root_, origin_, nonce_, blockNumber_, timestamp_, gasData_);\n    }\n\n    /**\n     * @notice Returns a State view over the given payload.\n     * @dev Will revert if the payload is not a state.\n     */\n    function castToState(bytes memory payload) internal pure returns (State) {\n        return castToState(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a State view.\n     * @dev Will revert if the memory view is not over a state.\n     */\n    function castToState(MemView memView) internal pure returns (State) {\n        if (!isState(memView)) revert UnformattedState();\n        return State.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted State.\n    function isState(MemView memView) internal pure returns (bool) {\n        return memView.len() == STATE_LENGTH;\n    }\n\n    /// @notice Returns the hash of a State, that could be later signed by a Guard to signal\n    /// that the state is invalid.\n    function hashInvalid(State state) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(stateInvalidSalt, keccak(state))\n        return state.unwrap().keccakSalted(STATE_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(State state) internal pure returns (MemView) {\n        return MemView.wrap(State.unwrap(state));\n    }\n\n    /// @notice Compares two State structures.\n    function equals(State a, State b) internal pure returns (bool) {\n        // Length of a State payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═══════════════════════════════════════════════ STATE HASHING ═══════════════════════════════════════════════════\n\n    /// @notice Returns the hash of the State.\n    /// @dev We are using the Merkle Root of a tree with two leafs (see below) as state hash.\n    function leaf(State state) internal pure returns (bytes32) {\n        (bytes32 leftLeaf_, bytes32 rightLeaf_) = state.subLeafs();\n        // Final hash is the parent of these leafs\n        return keccak256(bytes.concat(leftLeaf_, rightLeaf_));\n    }\n\n    /// @notice Returns \"sub-leafs\" of the State. Hash of these \"sub leafs\" is going to be used\n    /// as a \"state leaf\" in the \"Snapshot Merkle Tree\".\n    /// This enables proving that leftLeaf = (root, origin) was a part of the \"Snapshot Merkle Tree\",\n    /// by combining `rightLeaf` with the remainder of the \"Snapshot Merkle Proof\".\n    function subLeafs(State state) internal pure returns (bytes32 leftLeaf_, bytes32 rightLeaf_) {\n        MemView memView = state.unwrap();\n        // Left leaf is (root, origin)\n        leftLeaf_ = memView.prefix({len_: OFFSET_NONCE}).keccak();\n        // Right leaf is (metadata), or (nonce, blockNumber, timestamp)\n        rightLeaf_ = memView.sliceFrom({index_: OFFSET_NONCE}).keccak();\n    }\n\n    /// @notice Returns the left \"sub-leaf\" of the State.\n    function leftLeaf(bytes32 root_, uint32 origin_) internal pure returns (bytes32) {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(root_, origin_));\n    }\n\n    /// @notice Returns the right \"sub-leaf\" of the State.\n    function rightLeaf(uint32 nonce_, uint40 blockNumber_, uint40 timestamp_, GasData gasData_)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(nonce_, blockNumber_, timestamp_, gasData_));\n    }\n\n    // ═══════════════════════════════════════════════ STATE SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns a historical Merkle root from the Origin contract.\n    function root(State state) internal pure returns (bytes32) {\n        return state.unwrap().index({index_: OFFSET_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns domain of chain where the Origin contract is deployed.\n    function origin(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns nonce of Origin contract at the time, when `root` was the Merkle root.\n    function nonce(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when `root` was saved in Origin.\n    function blockNumber(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when `root` was saved in Origin.\n    /// @dev This is the timestamp according to the origin chain.\n    function timestamp(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n\n    /// @notice Returns gas data for the chain.\n    function gasData(State state) internal pure returns (GasData) {\n        return GasDataLib.wrapGasData(state.unwrap().indexUint({index_: OFFSET_GAS_DATA, bytes_: GAS_DATA_LENGTH}));\n    }\n}\n\n// contracts/libs/memory/BaseMessage.sol\n\n/// BaseMessage is a memory view over the base message supported by Origin-Destination\ntype BaseMessage is uint256;\n\nusing BaseMessageLib for BaseMessage global;\n\n/// BaseMessage structure represents a base message sent via the Origin-Destination contracts.\n/// - It only contains data relevant to the base message, the rest of data is encoded in the message header.\n/// - `sender` and `recipient` for EVM chains are EVM addresses casted to bytes32, while preserving left-alignment.\n/// - `tips` and `request` parameters are specified by a message sender\n/// \u003e Origin will calculate minimum tips for given request and content length, and will reject messages with tips\n/// lower than that.\n///\n/// # Memory layout of BaseMessage fields\n///\n/// | Position   | Field     | Type    | Bytes | Description                            |\n/// | ---------- | --------- | ------- | ----- | -------------------------------------- |\n/// | [000..032) | tips      | uint256 | 32    | Encoded tips paid on origin chain      |\n/// | [032..064) | sender    | bytes32 | 32    | Sender address on origin chain         |\n/// | [064..096) | recipient | bytes32 | 32    | Recipient address on destination chain |\n/// | [096..116) | request   | uint160 | 20    | Encoded request for message execution  |\n/// | [104..AAA) | content   | bytes   | ??    | Content to be passed to recipient      |\nlibrary BaseMessageLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_TIPS = 0;\n    uint256 private constant OFFSET_SENDER = 32;\n    uint256 private constant OFFSET_RECIPIENT = 64;\n    uint256 private constant OFFSET_REQUEST = OFFSET_RECIPIENT + TIPS_LENGTH;\n    uint256 private constant OFFSET_CONTENT = OFFSET_REQUEST + REQUEST_LENGTH;\n\n    // ═══════════════════════════════════════════════ BASE MESSAGE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted BaseMessage payload with provided fields.\n     * @param tips_         Encoded tips information\n     * @param sender_       Sender address on origin chain\n     * @param recipient_    Recipient address on destination chain\n     * @param request_      Encoded request for message execution\n     * @param content_      Raw content to be passed to recipient on destination chain\n     * @return Formatted base message\n     */\n    function formatBaseMessage(Tips tips_, bytes32 sender_, bytes32 recipient_, Request request_, bytes memory content_)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return abi.encodePacked(tips_, sender_, recipient_, request_, content_);\n    }\n\n    /**\n     * @notice Returns a BaseMessage view over the given payload.\n     * @dev Will revert if the payload is not a base message.\n     */\n    function castToBaseMessage(bytes memory payload) internal pure returns (BaseMessage) {\n        return castToBaseMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a BaseMessage view.\n     * @dev Will revert if the memory view is not over a base message payload.\n     */\n    function castToBaseMessage(MemView memView) internal pure returns (BaseMessage) {\n        if (!isBaseMessage(memView)) revert UnformattedBaseMessage();\n        return BaseMessage.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted BaseMessage.\n    function isBaseMessage(MemView memView) internal pure returns (bool) {\n        // Check if sender, recipient, tips fields exist\n        return (memView.len() \u003e= OFFSET_CONTENT);\n        // Content could be empty, so we don't check that\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(BaseMessage baseMessage) internal pure returns (MemView) {\n        return MemView.wrap(BaseMessage.unwrap(baseMessage));\n    }\n\n    /// @notice Returns baseMessage's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        // We hash \"tips\" and \"everything but tips\" to make tips proofs easier to verify\n        return MerkleMath.getParent(baseMessage.tips().leaf(), baseMessage.bodyLeaf());\n    }\n\n    /// @notice Returns hash for the \"everything but tips\" part of the base message.\n    function bodyLeaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_SENDER}).keccak();\n    }\n\n    // ═══════════════════════════════════════════ BASE MESSAGE SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips paid on origin chain.\n    function tips(BaseMessage baseMessage) internal pure returns (Tips) {\n        return TipsLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_TIPS, bytes_: TIPS_LENGTH})));\n    }\n\n    /// @notice Returns sender address on origin chain.\n    function sender(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_SENDER, bytes_: 32});\n    }\n\n    /// @notice Returns recipient address on destination chain.\n    function recipient(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_RECIPIENT, bytes_: 32});\n    }\n\n    /// @notice Returns an encoded request for message execution on destination chain.\n    function request(BaseMessage baseMessage) internal pure returns (Request) {\n        return RequestLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_REQUEST, bytes_: REQUEST_LENGTH})));\n    }\n\n    /// @notice Returns an untyped memory view over the content to be passed to recipient.\n    function content(BaseMessage baseMessage) internal pure returns (MemView) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_CONTENT});\n    }\n}\n\n// contracts/base/MessagingBase.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for all messaging contracts.\n * - Provides context on the local chain's domain.\n * - Provides ownership functionality.\n * - Will be providing pausing functionality when it is implemented.\n */\nabstract contract MessagingBase is MultiCallable, Versioned, Ownable2StepUpgradeable {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @notice Domain of the local chain, set once upon contract creation\n    uint32 public immutable localDomain;\n    // @notice Domain of the Synapse chain, set once upon contract creation\n    uint32 public immutable synapseDomain;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev gap for upgrade safety\n    uint256[50] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    constructor(string memory version_, uint32 synapseDomain_) Versioned(version_) {\n        localDomain = ChainContext.chainId();\n        synapseDomain = synapseDomain_;\n    }\n\n    // TODO: Implement pausing\n\n    /**\n     * @dev Should be impossible to renounce ownership;\n     * we override OpenZeppelin OwnableUpgradeable's\n     * implementation of renounceOwnership to make it a no-op\n     */\n    function renounceOwnership() public override onlyOwner {} //solhint-disable-line no-empty-blocks\n}\n\n// contracts/libs/memory/Message.sol\n\n/// Message is a memory over over a formatted message payload.\ntype Message is uint256;\n\nusing MessageLib for Message global;\n\n/// Library for formatting the various messages supported by Origin and Destination.\n///\n/// # Message memory layout\n///\n/// | Position   | Field  | Type    | Bytes | Description                                             |\n/// | ---------- | ------ | ------- | ----- | ------------------------------------------------------- |\n/// | [000..017) | header | uint136 | 17    | Encoded general routing information for the message     |\n/// | [017..AAA) | body   | bytes   | ??    | Formatted payload (according to flag) with message body |\nlibrary MessageLib {\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MemViewLib for bytes;\n    using HeaderLib for MemView;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_HEADER = 0;\n    uint256 private constant OFFSET_BODY = OFFSET_HEADER + HEADER_LENGTH;\n\n    // ══════════════════════════════════════════════════ MESSAGE ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns formatted message with provided fields.\n     * @param header_   Encoded general routing information for the message\n     * @param body_     Formatted payload (according to flag) with message body\n     * @return Formatted message\n     */\n    function formatMessage(Header header_, bytes memory body_) internal pure returns (bytes memory) {\n        return abi.encodePacked(header_, body_);\n    }\n\n    /**\n     * @notice Returns a Message view over for the given payload.\n     * @dev Will revert if the payload is not a message payload.\n     */\n    function castToMessage(bytes memory payload) internal pure returns (Message) {\n        return castToMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Message view.\n     * @dev Will revert if the memory view is not over a message payload.\n     */\n    function castToMessage(MemView memView) internal pure returns (Message) {\n        if (!isMessage(memView)) revert UnformattedMessage();\n        return Message.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Message.\n     */\n    function isMessage(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Check if headers exist in the payload\n        if (length \u003c OFFSET_BODY) return false;\n        // Check that Header is valid\n        uint256 paddedHeader = _header(memView);\n        if (!HeaderLib.isHeader(paddedHeader)) return false;\n        // Check that body is formatted according to the flag\n        // Only Base/Manager message flags exist\n        if (HeaderLib.wrapPadded(paddedHeader).flag() == MessageFlag.Base) {\n            // Check if body is a formatted base message\n            return _body(memView).isBaseMessage();\n        } else {\n            // Check if body is a formatted calldata for AgentManager call\n            return _body(memView).isCallData();\n        }\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Message message) internal pure returns (MemView) {\n        return MemView.wrap(Message.unwrap(message));\n    }\n\n    /// @notice Returns message's hash: a leaf to be inserted in the Merkle tree.\n    function leaf(Message message) internal pure returns (bytes32) {\n        // We hash header and body separately to make message proofs easier to verify\n        Header header_ = message.header();\n        // Only Base/Manager message flags exist\n        if (header_.flag() == MessageFlag.Base) {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToBaseMessage().leaf());\n        } else {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToCallData().leaf());\n        }\n    }\n\n    // ══════════════════════════════════════════════ MESSAGE SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns message's encoded header field.\n    function header(Message message) internal pure returns (Header) {\n        return HeaderLib.wrapPadded((message.unwrap().indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH})));\n    }\n\n    /// @notice Returns message's body field as an untyped memory view.\n    function body(Message message) internal pure returns (MemView) {\n        MemView memView = message.unwrap();\n        return _body(memView);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns message's padded header without checking that it is a valid header.\n    function _header(MemView memView) private pure returns (uint256) {\n        return memView.indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH});\n    }\n\n    /// @dev Returns an untyped memory view over the body field without checking\n    /// if the whole payload or the body are properly formatted.\n    function _body(MemView memView) private pure returns (MemView) {\n        return memView.sliceFrom({index_: OFFSET_BODY});\n    }\n}\n\n// contracts/base/AgentSecured.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for messaging contracts that are secured by the agent manager.\n * `AgentSecured` relies on `AgentManager` to provide the following functionality:\n * - Keep track of agents and their statuses.\n * - Pass agent-signed statements that were verified by the agent manager.\n * - These statements are considered valid indefinitely, unless the agent is disputed.\n * - Disputes are opened and resolved by the agent manager.\n * \u003e `AgentSecured` implementation should never use statements signed by agents that are disputed.\n */\nabstract contract AgentSecured is MessagingBase, IAgentSecured {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    address public immutable agentManager;\n\n    /// @inheritdoc IAgentSecured\n    address public immutable inbox;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    // (agent index =\u003e their dispute status: flag, openedAt, resolvedAt)\n    mapping(uint32 =\u003e DisputeStatus) internal _disputes;\n\n    /// @dev gap for upgrade safety\n    uint256[49] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    modifier onlyAgentManager() {\n        if (msg.sender != agentManager) revert CallerNotAgentManager();\n        _;\n    }\n\n    modifier onlyInbox() {\n        if (msg.sender != inbox) revert CallerNotInbox();\n        _;\n    }\n\n    constructor(string memory version_, uint32 synapseDomain_, address agentManager_, address inbox_)\n        MessagingBase(version_, synapseDomain_)\n    {\n        agentManager = agentManager_;\n        inbox = inbox_;\n    }\n\n    // ════════════════════════════════════════════ ONLY AGENT MANAGER ═════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external onlyAgentManager {\n        uint40 openedAt = ChainContext.blockTimestamp();\n        DisputeStatus memory status = DisputeStatus({flag: DisputeFlag.Pending, openedAt: openedAt, resolvedAt: 0});\n        _disputes[guardIndex] = status;\n        _disputes[notaryIndex] = status;\n    }\n\n    /// @inheritdoc IAgentSecured\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external onlyAgentManager {\n        // Update the dispute status of the slashed agent first.\n        uint40 resolvedAt = ChainContext.blockTimestamp();\n        _disputes[slashedIndex].flag = DisputeFlag.Slashed;\n        _disputes[slashedIndex].resolvedAt = resolvedAt;\n        // Mark the rival agent as not disputed, if there was an ongoing dispute.\n        if (rivalIndex != 0) {\n            _disputes[rivalIndex].flag = DisputeFlag.None;\n            _disputes[rivalIndex].resolvedAt = resolvedAt;\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function agentStatus(address agent) external view returns (AgentStatus memory) {\n        return _agentStatus(agent);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status) {\n        return _getAgent(index);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory) {\n        return _disputes[agentIndex];\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns status of the given agent: (flag, domain, index).\n    function _agentStatus(address agent) internal view returns (AgentStatus memory) {\n        return IAgentManager(agentManager).agentStatus(agent);\n    }\n\n    /// @dev Returns agent and their status for a given agent index. Returns zero values for non existing indexes.\n    function _getAgent(uint256 index) internal view returns (address agent, AgentStatus memory status) {\n        return IAgentManager(agentManager).getAgent(index);\n    }\n\n    /// @dev Checks if a Dispute exists for the given Notary. This function returns true, if\n    /// Notary is in ongoing Dispute, or if Dispute was resolved not in Notary's favor.\n    /// In both cases we can't trust Notary's data.\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeExists(uint32 notaryIndex) internal view returns (bool) {\n        return _disputes[notaryIndex].flag != DisputeFlag.None;\n    }\n\n    /// @dev Checks if a Notary recently won a Dispute and is still in the \"post-dispute\" timeout period.\n    /// In this period we still can't trust Notary's data, though we can optimistically assume that\n    /// that the data will be correct after the timeout (assuming no new Disputes are opened).\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeTimeout(uint32 notaryIndex) internal view returns (bool) {\n        DisputeStatus memory status = _disputes[notaryIndex];\n        // Exit early if Notary is in ongoing Dispute / slashed.\n        if (status.flag != DisputeFlag.None) return false;\n        // Check if Notary has been in any Dispute at all.\n        if (status.openedAt == 0) return false;\n        // Otherwise check if the Dispute timeout is still active.\n        return block.timestamp \u003c status.resolvedAt + DISPUTE_TIMEOUT_NOTARY;\n    }\n}\n\n// contracts/hubs/StateHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StateHub` is a parent contract for `Origin`. It is responsible for the following:\n/// - Keeping track of the historical Origin Merkle Tree containing all the message hashes.\n/// - Keeping track of the historical Origin States, as well as verifying their validity.\nabstract contract StateHub is AgentSecured, StateHubEvents, IStateHub {\n    using SafeCast for uint256;\n    using StateLib for bytes;\n\n    struct OriginState {\n        uint40 blockNumber;\n        uint40 timestamp;\n        GasData gasData;\n    }\n    // Bits left for tight packing: 80\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Historical Merkle Tree\n    /// Note: Takes two storage slots\n    HistoricalTree private _tree;\n\n    /// @dev All historical contract States\n    OriginState[] private _originStates;\n\n    /// @dev gap for upgrade safety\n    uint256[47] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IStateHub\n    function isValidState(bytes memory statePayload) external view returns (bool isValid) {\n        // This will revert if payload is not a formatted state\n        State state = statePayload.castToState();\n        return _isValidState(state);\n    }\n\n    /// @inheritdoc IStateHub\n    function statesAmount() external view returns (uint256) {\n        return _originStates.length;\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestLatestState() external view returns (bytes memory stateData) {\n        // This never underflows, assuming the contract was initialized\n        return suggestState(_nextNonce() - 1);\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestState(uint32 nonce) public view returns (bytes memory stateData) {\n        // This will revert if nonce is out of range\n        bytes32 root = _tree.root(nonce);\n        return _formatOriginState(_originStates[nonce], root, localDomain, nonce);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Initializes the saved states list by inserting a state for an empty Merkle Tree.\n    function _initializeStates() internal {\n        // This should only be called once, when the contract is initialized\n        // This will revert if _tree.roots is non-empty\n        bytes32 savedRoot = _tree.initializeRoots();\n        // Save root for empty merkle _tree with block number and timestamp of initialization\n        _saveState(savedRoot, _toOriginState());\n    }\n\n    /// @dev Inserts leaf into the Merkle Tree and saves the updated origin State.\n    function _insertAndSave(bytes32 leaf) internal {\n        bytes32 newRoot = _tree.insert(leaf);\n        _saveState(newRoot, _toOriginState());\n    }\n\n    /// @dev Saves an updated state of the Origin contract\n    function _saveState(bytes32 root, OriginState memory state) internal {\n        uint32 nonce = _nextNonce();\n        _originStates.push(state);\n        // Emit event with raw state data\n        emit StateSaved(_formatOriginState(state, root, localDomain, nonce));\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns nonce of the next sent message: the amount of saved States so far.\n    /// This always equals to \"total amount of sent messages\" plus 1.\n    function _nextNonce() internal view returns (uint32) {\n        // TODO: consider using more than 32 bits for origin nonces\n        return _originStates.length.toUint32();\n    }\n\n    /// @dev Checks if a state is valid, i.e. if it matches the historical one.\n    /// Reverts, if state refers to another Origin contract.\n    function _isValidState(State state) internal view returns (bool) {\n        // Check if state refers to this contract\n        if (state.origin() != localDomain) revert IncorrectOriginDomain();\n        // Check if nonce exists\n        uint32 nonce = state.nonce();\n        if (nonce \u003e= _originStates.length) return false;\n        // Check if state root matches the historical one\n        if (state.root() != _tree.root(nonce)) return false;\n        // Check if state metadata matches the historical one\n        return _areEqual(state, _originStates[nonce]);\n    }\n\n    // ═════════════════════════════════════════════ STRUCT FORMATTING ═════════════════════════════════════════════════\n\n    /// @dev Returns a formatted payload for a stored OriginState.\n    function _formatOriginState(OriginState memory originState, bytes32 root, uint32 origin, uint32 nonce)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return StateLib.formatState({\n            root_: root,\n            origin_: origin,\n            nonce_: nonce,\n            blockNumber_: originState.blockNumber,\n            timestamp_: originState.timestamp,\n            gasData_: originState.gasData\n        });\n    }\n\n    /// @dev Child contract should implement the logic for getting the current gas data from the gas oracle\n    /// to be saved as part of the Origin State.\n    // solhint-disable-next-line ordering\n    function _fetchGasData() internal view virtual returns (GasData);\n\n    /// @dev Returns a OriginState struct to save in the contract.\n    function _toOriginState() internal view returns (OriginState memory originState) {\n        originState.blockNumber = ChainContext.blockNumber();\n        originState.timestamp = ChainContext.blockTimestamp();\n        originState.gasData = _fetchGasData();\n    }\n\n    /// @dev Checks that a state and its Origin representation are equal.\n    function _areEqual(State state, OriginState memory originState) internal pure returns (bool) {\n        return state.blockNumber() == originState.blockNumber \u0026\u0026 state.timestamp() == originState.timestamp;\n    }\n}\n\n// contracts/Origin.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Origin` contract is used for sending messages to remote chains. It is done\n/// by inserting the message hashes into the Origin Merkle, which makes it possible to\n/// prove that message was sent using the Merkle proof against the Origin Merkle Root. This essentially\n/// compresses the list of messages into a single 32-byte value that needs to be stored on the destination chain.\n/// `Origin` is responsible for the following:\n/// - Formatting the sent message payloads, and inserting their hashes into the Origin Merkle Tree.\n/// - Keeping track of its own historical states (see parent contract `StateHub`).\n/// - Enforcing minimum tip values for sent base messages based on the provided execution requests.\n/// - Distributing the collected tips upon request from a local `AgentManager` contract.\ncontract Origin is StateHub, OriginEvents, InterfaceOrigin {\n    using MemViewLib for bytes;\n    using MessageLib for bytes;\n    using TipsLib for bytes;\n    using TypeCasts for address;\n\n    address public immutable gasOracle;\n\n    modifier onlyRemoteDestination(uint32 destination) {\n        if (destination == localDomain) revert IncorrectDestinationDomain();\n        _;\n    }\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_, address gasOracle_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {\n        gasOracle = gasOracle_;\n    }\n\n    /// @notice Initializes Origin contract:\n    /// - msg.sender is set as contract owner\n    /// - State of \"empty merkle tree\" is saved\n    function initialize() external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize \"states\": state of an \"empty merkle tree\" is saved\n        _initializeStates();\n    }\n\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable onlyRemoteDestination(destination) returns (uint32 messageNonce, bytes32 messageHash) {\n        // Check that content is not too large\n        if (content.length \u003e MAX_CONTENT_BYTES) revert ContentLengthTooBig();\n        // This will revert if msg.value is lower than value of minimum tips\n        Tips tips = _getMinimumTips(destination, paddedRequest, content.length).matchValue(msg.value);\n        Request request = RequestLib.wrapPadded(paddedRequest);\n        // Format the BaseMessage body\n        bytes memory body = BaseMessageLib.formatBaseMessage({\n            sender_: msg.sender.addressToBytes32(),\n            recipient_: recipient,\n            tips_: tips,\n            request_: request,\n            content_: content\n        });\n        // Send the message\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Base, body);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        onlyAgentManager\n        onlyRemoteDestination(destination)\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // AgentManager (checked via modifier) is responsible for constructing the calldata payload correctly.\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Manager, payload);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function withdrawTips(address recipient, uint256 amount) external onlyAgentManager {\n        if (address(this).balance \u003c amount) revert InsufficientEthBalance();\n        (bool success,) = recipient.call{value: amount}(\"\");\n        if (!success) revert EthTransferFailed();\n        emit TipWithdrawalCompleted(recipient, amount);\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue)\n    {\n        return _getMinimumTips(destination, paddedRequest, contentLength).value();\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Sends the given message to the specified destination. Message hash is inserted\n    /// into the Origin Merkle Tree, which will enable message execution on destination chain.\n    function _sendMessage(uint32 destination, uint32 optimisticPeriod, MessageFlag flag, bytes memory body)\n        internal\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // Format the message header\n        messageNonce = _nextNonce();\n        Header header = flag.encodeHeader({\n            origin_: localDomain,\n            nonce_: messageNonce,\n            destination_: destination,\n            optimisticPeriod_: optimisticPeriod\n        });\n        // Format the full message payload\n        bytes memory msgPayload = MessageLib.formatMessage(header, body);\n        // Insert new leaf into the Origin Merkle Tree and save the updated state\n        messageHash = msgPayload.castToMessage().leaf();\n        _insertAndSave(messageHash);\n        // Emit event with message information\n        emit Sent(messageHash, messageNonce, destination, msgPayload);\n        // Update the gas oracle data. We do this after the provided tips are checked so that\n        // the provided message is sent in the event that the gas oracle data is updated to a higher value.\n        InterfaceGasOracle(gasOracle).updateGasData(destination);\n        // TODO: consider doing this before the message is sent, while adjusting GasOracle.getMinimumTips() to\n        // use the pending gas oracle data.\n    }\n\n    /// @dev Returns the minimum tips for sending a message to the given destination with the given request and content.\n    function _getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        internal\n        view\n        returns (Tips)\n    {\n        return\n            TipsLib.wrapPadded(InterfaceGasOracle(gasOracle).getMinimumTips(destination, paddedRequest, contentLength));\n    }\n\n    /// @dev Gets the current gas data from the gas oracle to be saved as part of the Origin State.\n    function _fetchGasData() internal view override returns (GasData) {\n        return GasDataLib.wrapGasData(InterfaceGasOracle(gasOracle).getGasData());\n    }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[],"name":"CallerNotAgentManager","type":"error"},{"inputs":[],"name":"IncorrectVersionLength","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"agentManager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"agent","type":"address"}],"name":"agentStatus","outputs":[{"components":[{"internalType":"enum AgentFlag","name":"flag","type":"uint8"},{"internalType":"uint32","name":"domain","type":"uint32"},{"internalType":"uint32","name":"index","type":"uint32"}],"internalType":"struct AgentStatus","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getAgent","outputs":[{"internalType":"address","name":"agent","type":"address"},{"components":[{"internalType":"enum AgentFlag","name":"flag","type":"uint8"},{"internalType":"uint32","name":"domain","type":"uint32"},{"internalType":"uint32","name":"index","type":"uint32"}],"internalType":"struct AgentStatus","name":"status","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"inbox","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"agentIndex","type":"uint32"}],"name":"latestDisputeStatus","outputs":[{"components":[{"internalType":"enum DisputeFlag","name":"flag","type":"uint8"},{"internalType":"uint40","name":"openedAt","type":"uint40"},{"internalType":"uint40","name":"resolvedAt","type":"uint40"}],"internalType":"struct DisputeStatus","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"localDomain","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bool","name":"allowFailure","type":"bool"},{"internalType":"bytes","name":"callData","type":"bytes"}],"internalType":"struct MultiCallable.Call[]","name":"calls","type":"tuple[]"}],"name":"multicall","outputs":[{"components":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"bytes","name":"returnData","type":"bytes"}],"internalType":"struct MultiCallable.Result[]","name":"callResults","type":"tuple[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"guardIndex","type":"uint32"},{"internalType":"uint32","name":"notaryIndex","type":"uint32"}],"name":"openDispute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"slashedIndex","type":"uint32"},{"internalType":"uint32","name":"rivalIndex","type":"uint32"}],"name":"resolveDispute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"synapseDomain","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"versionString","type":"string"}],"stateMutability":"view","type":"function"}],"userDoc":{"kind":"user","methods":{"agentManager()":{"notice":"Returns the address of the local AgentManager contract, which is treated as the \"source of truth\" for agent statuses."},"agentStatus(address)":{"notice":"Returns (flag, domain, index) for a given agent. See Structures.sol for details."},"getAgent(uint256)":{"notice":"Returns agent address and their current status for a given agent index."},"inbox()":{"notice":"Returns the address of the local Inbox contract, which is treated as the \"source of truth\" for agent-signed statements."},"latestDisputeStatus(uint32)":{"notice":"Returns (flag, openedAt, resolvedAt) that describes the latest status of the latest dispute for an agent with a given index."},"localDomain()":{"notice":"Domain of the local chain, set once upon contract creation"},"multicall((bool,bytes)[])":{"notice":"Aggregates a few calls to this contract into one multicall without modifying `msg.sender`."},"openDispute(uint32,uint32)":{"notice":"Local AgentManager should call this function to indicate that a dispute between a Guard and a Notary has been opened."},"resolveDispute(uint32,uint32)":{"notice":"Local AgentManager should call this function to indicate that a dispute has been resolved due to one of the agents being slashed. \u003e `rivalIndex` will be ZERO, if the slashed agent was not in the Dispute."}},"notice":"Base contract for messaging contracts that are secured by the agent manager. `AgentSecured` relies on `AgentManager` to provide the following functionality: - Keep track of agents and their statuses. - Pass agent-signed statements that were verified by the agent manager. - These statements are considered valid indefinitely, unless the agent is disputed. - Disputes are opened and resolved by the agent manager. \u003e `AgentSecured` implementation should never use statements signed by agents that are disputed.","version":1},"developerDoc":{"kind":"dev","methods":{"acceptOwnership()":{"details":"The new owner accepts the ownership transfer."},"agentStatus(address)":{"details":"Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud, but their status is not updated to Slashed yet.","params":{"agent":"Agent address"},"returns":{"_0":"Status for the given agent: (flag, domain, index)."}},"getAgent(uint256)":{"details":"Will return empty values if agent with given index doesn't exist.","params":{"index":"Agent index in the Agent Merkle Tree"},"returns":{"agent":"   Agent address","status":"  Status for the given agent: (flag, domain, index)"}},"latestDisputeStatus(uint32)":{"details":"Will return empty values if agent with given index doesn't exist.","params":{"agentIndex":"Agent index in the Agent Merkle Tree"},"returns":{"_0":"Latest dispute status for the given agent: (flag, openedAt, resolvedAt)"}},"openDispute(uint32,uint32)":{"params":{"guardIndex":"Index of the Guard in the Agent Merkle Tree","notaryIndex":"Index of the Notary in the Agent Merkle Tree"}},"owner()":{"details":"Returns the address of the current owner."},"pendingOwner()":{"details":"Returns the address of the pending owner."},"renounceOwnership()":{"details":"Should be impossible to renounce ownership; we override OpenZeppelin OwnableUpgradeable's implementation of renounceOwnership to make it a no-op"},"resolveDispute(uint32,uint32)":{"params":{"rivalIndex":"Index of the their Dispute Rival in the Agent Merkle Tree","slashedIndex":"Index of the slashed agent in the Agent Merkle Tree"}},"transferOwnership(address)":{"details":"Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. Can only be called by the current owner."}},"stateVariables":{"__GAP":{"details":"gap for upgrade safety"},"inbox":{"details":"Inbox passes verified agent statements to `IAgentSecured` contract."}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"CallerNotAgentManager\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectVersionLength\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferStarted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"agentManager\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"agent\",\"type\":\"address\"}],\"name\":\"agentStatus\",\"outputs\":[{\"components\":[{\"internalType\":\"enum AgentFlag\",\"name\":\"flag\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"domain\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"index\",\"type\":\"uint32\"}],\"internalType\":\"struct AgentStatus\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getAgent\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"agent\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"enum AgentFlag\",\"name\":\"flag\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"domain\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"index\",\"type\":\"uint32\"}],\"internalType\":\"struct AgentStatus\",\"name\":\"status\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"inbox\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"agentIndex\",\"type\":\"uint32\"}],\"name\":\"latestDisputeStatus\",\"outputs\":[{\"components\":[{\"internalType\":\"enum DisputeFlag\",\"name\":\"flag\",\"type\":\"uint8\"},{\"internalType\":\"uint40\",\"name\":\"openedAt\",\"type\":\"uint40\"},{\"internalType\":\"uint40\",\"name\":\"resolvedAt\",\"type\":\"uint40\"}],\"internalType\":\"struct DisputeStatus\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"localDomain\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"allowFailure\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"struct MultiCallable.Call[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"multicall\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"struct MultiCallable.Result[]\",\"name\":\"callResults\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"guardIndex\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"notaryIndex\",\"type\":\"uint32\"}],\"name\":\"openDispute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"slashedIndex\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"rivalIndex\",\"type\":\"uint32\"}],\"name\":\"resolveDispute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"synapseDomain\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"versionString\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"acceptOwnership()\":{\"details\":\"The new owner accepts the ownership transfer.\"},\"agentStatus(address)\":{\"details\":\"Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud, but their status is not updated to Slashed yet.\",\"params\":{\"agent\":\"Agent address\"},\"returns\":{\"_0\":\"Status for the given agent: (flag, domain, index).\"}},\"getAgent(uint256)\":{\"details\":\"Will return empty values if agent with given index doesn't exist.\",\"params\":{\"index\":\"Agent index in the Agent Merkle Tree\"},\"returns\":{\"agent\":\"   Agent address\",\"status\":\"  Status for the given agent: (flag, domain, index)\"}},\"latestDisputeStatus(uint32)\":{\"details\":\"Will return empty values if agent with given index doesn't exist.\",\"params\":{\"agentIndex\":\"Agent index in the Agent Merkle Tree\"},\"returns\":{\"_0\":\"Latest dispute status for the given agent: (flag, openedAt, resolvedAt)\"}},\"openDispute(uint32,uint32)\":{\"params\":{\"guardIndex\":\"Index of the Guard in the Agent Merkle Tree\",\"notaryIndex\":\"Index of the Notary in the Agent Merkle Tree\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pendingOwner()\":{\"details\":\"Returns the address of the pending owner.\"},\"renounceOwnership()\":{\"details\":\"Should be impossible to renounce ownership; we override OpenZeppelin OwnableUpgradeable's implementation of renounceOwnership to make it a no-op\"},\"resolveDispute(uint32,uint32)\":{\"params\":{\"rivalIndex\":\"Index of the their Dispute Rival in the Agent Merkle Tree\",\"slashedIndex\":\"Index of the slashed agent in the Agent Merkle Tree\"}},\"transferOwnership(address)\":{\"details\":\"Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. Can only be called by the current owner.\"}},\"stateVariables\":{\"__GAP\":{\"details\":\"gap for upgrade safety\"},\"inbox\":{\"details\":\"Inbox passes verified agent statements to `IAgentSecured` contract.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"agentManager()\":{\"notice\":\"Returns the address of the local AgentManager contract, which is treated as the \\\"source of truth\\\" for agent statuses.\"},\"agentStatus(address)\":{\"notice\":\"Returns (flag, domain, index) for a given agent. See Structures.sol for details.\"},\"getAgent(uint256)\":{\"notice\":\"Returns agent address and their current status for a given agent index.\"},\"inbox()\":{\"notice\":\"Returns the address of the local Inbox contract, which is treated as the \\\"source of truth\\\" for agent-signed statements.\"},\"latestDisputeStatus(uint32)\":{\"notice\":\"Returns (flag, openedAt, resolvedAt) that describes the latest status of the latest dispute for an agent with a given index.\"},\"localDomain()\":{\"notice\":\"Domain of the local chain, set once upon contract creation\"},\"multicall((bool,bytes)[])\":{\"notice\":\"Aggregates a few calls to this contract into one multicall without modifying `msg.sender`.\"},\"openDispute(uint32,uint32)\":{\"notice\":\"Local AgentManager should call this function to indicate that a dispute between a Guard and a Notary has been opened.\"},\"resolveDispute(uint32,uint32)\":{\"notice\":\"Local AgentManager should call this function to indicate that a dispute has been resolved due to one of the agents being slashed. \u003e `rivalIndex` will be ZERO, if the slashed agent was not in the Dispute.\"}},\"notice\":\"Base contract for messaging contracts that are secured by the agent manager. `AgentSecured` relies on `AgentManager` to provide the following functionality: - Keep track of agents and their statuses. - Pass agent-signed statements that were verified by the agent manager. - These statements are considered valid indefinitely, unless the agent is disputed. - Disputes are opened and resolved by the agent manager. \u003e `AgentSecured` implementation should never use statements signed by agents that are disputed.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Origin.sol\":\"AgentSecured\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Origin.sol\":{\"keccak256\":\"0x96775924f147f3d1f8df8cdf56731fe52a15af8d8e12e608efb8158c112b18cd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e642a27f5fab3c62b4c02e9754e9e42b1cf2e5381dbea9d3d106d23b7772ebe6\",\"dweb:/ipfs/QmUwn7ZyBvPkjnMuK8ZMSexBUdNQnVtxwyoAyT4DXLQjra\"]}},\"version\":1}"},"hashes":{"acceptOwnership()":"79ba5097","agentManager()":"7622f78d","agentStatus(address)":"28f3fac9","getAgent(uint256)":"2de5aaf7","inbox()":"fb0e722b","latestDisputeStatus(uint32)":"dfadd81a","localDomain()":"8d3638f4","multicall((bool,bytes)[])":"60fc8466","openDispute(uint32,uint32)":"a2155c34","owner()":"8da5cb5b","pendingOwner()":"e30c3978","renounceOwnership()":"715018a6","resolveDispute(uint32,uint32)":"61169218","synapseDomain()":"717b8638","transferOwnership(address)":"f2fde38b","version()":"54fd4d50"}},"solidity/Origin.sol:BaseMessageLib":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220149b7aee23b2da92d057330166b79742228abc68e24e56b600c5f9d5cc65612864736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220149b7aee23b2da92d057330166b79742228abc68e24e56b600c5f9d5cc65612864736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/OriginEvents.sol\n\n/// @notice A collection of events emitted by the Origin contract\nabstract contract OriginEvents {\n    /**\n     * @notice Emitted when a new message is sent.\n     * @param messageHash   Hash of message; the leaf inserted to the Merkle tree for the message\n     * @param nonce         Nonce of sent message (starts from 1)\n     * @param destination   Destination domain\n     * @param message       Raw bytes of message\n     */\n    event Sent(bytes32 indexed messageHash, uint32 indexed nonce, uint32 indexed destination, bytes message);\n\n    /**\n     * @notice Emitted when a tip withdrawal is completed.\n     * @param actor     Actor address\n     * @param tip       Tip value, denominated in local domain's wei\n     */\n    event TipWithdrawalCompleted(address actor, uint256 tip);\n}\n\n// contracts/events/StateHubEvents.sol\n\n/// @notice A collection of events emitted by the StateHub contract\nabstract contract StateHubEvents {\n    /**\n     * @notice Emitted when a new Origin State is saved after a message was sent.\n     * @param state     Raw payload with state data\n     */\n    event StateSaved(bytes state);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n    /**\n     * @notice Check that a given state is valid: matches the historical state of Origin contract.\n     * Note: any Agent including an invalid state in their snapshot will be slashed\n     * upon providing the snapshot and agent signature for it to Origin contract.\n     * @dev Will revert if any of these is true:\n     *  - State payload is not properly formatted.\n     * @param statePayload      Raw payload with state data\n     * @return isValid          Whether the provided state is valid\n     */\n    function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns the amount of saved states so far.\n     * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n     */\n    function statesAmount() external view returns (uint256);\n\n    /**\n     * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @return statePayload     Raw payload with the latest state data\n     */\n    function suggestLatestState() external view returns (bytes memory statePayload);\n\n    /**\n     * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @param nonce             Historical nonce to form a state\n     * @return statePayload     Raw payload with historical state data\n     */\n    function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/InterfaceGasOracle.sol\n\ninterface InterfaceGasOracle {\n    /**\n     * @notice Fetches the latest gas data for the chain from `Destination` contract,\n     * and uses it to update the oracle values for the requested chain.\n     * @param domain    Domain to update the gas data for\n     */\n    function updateGasData(uint32 domain) external;\n\n    /**\n     * @notice Returns the gas data for the local chain.\n     */\n    function getGasData() external view returns (uint256 paddedGasData);\n\n    /**\n     * @notice Returns the gas data for the given domain, in the decoded format.\n     * @param domain        Domain of chain to get gas data for\n     * @return gasPrice     Gas price for the chain (in Wei per gas unit)\n     * @return dataPrice    Calldata price (in Wei per byte of content)\n     * @return execBuffer   Tx fee safety buffer for message execution (in Wei)\n     * @return amortAttCost Amortized cost for attestation submission (in Wei)\n     * @return etherPrice   Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n     * @return markup       Markup for the message execution (in BWAD)\n     */\n    function getDecodedGasData(uint32 domain)\n        external\n        view\n        returns (\n            uint256 gasPrice,\n            uint256 dataPrice,\n            uint256 execBuffer,\n            uint256 amortAttCost,\n            uint256 etherPrice,\n            uint256 markup\n        );\n\n    /**\n     * @notice Returns the minimum tips for sending a message to a given destination.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return paddedTips       Padded encoded minimum tips information\n     */\n    function getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 paddedTips);\n}\n\n// contracts/interfaces/InterfaceOrigin.sol\n\ninterface InterfaceOrigin {\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /**\n     * @notice Send a message to the recipient located on destination domain.\n     * @dev Recipient has to conform to IMessageRecipient interface, otherwise message won't be delivered.\n     * Will revert if any of these is true:\n     * - `destination` is equal to contract's local domain\n     * - `content` length is greater than `MAX_CONTENT_BYTES`\n     * - `msg.value` is lower than value of minimum tips for the given message\n     * @param destination           Domain of destination chain\n     * @param recipient             Address of recipient on destination chain as bytes32\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param paddedRequest         Padded encoded message execution request on destination chain\n     * @param content               Raw bytes content of message\n     * @return messageNonce         Nonce of the sent message\n     * @return messageHash          Hash of the sent message\n     */\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable returns (uint32 messageNonce, bytes32 messageHash);\n\n    /**\n     * @notice Send a manager message to the destination domain.\n     * @dev This could only be called by AgentManager, which takes care of encoding the calldata payload.\n     * Note: (msgOrigin, proofMaturity) security args will be added to payload on the destination chain\n     * so that the AgentManager could verify where the Manager Message came from and how mature is the proof.\n     * Note: function is not payable, as no tips are required for sending a manager message.\n     * Will revert if `destination` is equal to contract's local domain.\n     * @param destination           Domain of destination chain\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param payload               Payload for calling AgentManager on destination chain (with extra security args)\n     */\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        returns (uint32 messageNonce, bytes32 messageHash);\n\n    // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Withdraws locked base message tips to the recipient.\n     * @dev Could only be called by a local AgentManager.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function withdrawTips(address recipient, uint256 amount) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the minimum tips value for sending a message to a given destination.\n     * @dev Using at least `tipsValue` as `msg.value` for `sendBaseMessage()`\n     * will guarantee that the message will be accepted.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return tipsValue        Minimum tips value for a message to be accepted\n     */\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue);\n}\n\n// contracts/libs/Constants.sol\n\n// Here we define common constants to enable their easier reusing later.\n\n// ══════════════════════════════════ MERKLE ═══════════════════════════════════\n/// @dev Height of the Agent Merkle Tree\nuint256 constant AGENT_TREE_HEIGHT = 32;\n/// @dev Height of the Origin Merkle Tree\nuint256 constant ORIGIN_TREE_HEIGHT = 32;\n/// @dev Height of the Snapshot Merkle Tree. Allows up to 64 leafs, e.g. up to 32 states\nuint256 constant SNAPSHOT_TREE_HEIGHT = 6;\n// ══════════════════════════════════ STRUCTS ══════════════════════════════════\n/// @dev See Attestation.sol: (bytes32,bytes32,uint32,uint40,uint40): 32+32+4+5+5\nuint256 constant ATTESTATION_LENGTH = 78;\n/// @dev See GasData.sol: (uint16,uint16,uint16,uint16,uint16,uint16): 2+2+2+2+2+2\nuint256 constant GAS_DATA_LENGTH = 12;\n/// @dev See Receipt.sol: (uint32,uint32,bytes32,bytes32,uint8,address,address,address): 4+4+32+32+1+20+20+20\nuint256 constant RECEIPT_LENGTH = 133;\n/// @dev See State.sol: (bytes32,uint32,uint32,uint40,uint40,GasData): 32+4+4+5+5+len(GasData)\nuint256 constant STATE_LENGTH = 50 + GAS_DATA_LENGTH;\n/// @dev Maximum amount of states in a single snapshot. Each state produces two leafs in the tree\nuint256 constant SNAPSHOT_MAX_STATES = 1 \u003c\u003c (SNAPSHOT_TREE_HEIGHT - 1);\n// ══════════════════════════════════ MESSAGE ══════════════════════════════════\n/// @dev See Header.sol: (uint8,uint32,uint32,uint32,uint32): 1+4+4+4+4\nuint256 constant HEADER_LENGTH = 17;\n/// @dev See Request.sol: (uint96,uint64,uint32): 12+8+4\nuint256 constant REQUEST_LENGTH = 24;\n/// @dev See Tips.sol: (uint64,uint64,uint64,uint64): 8+8+8+8\nuint256 constant TIPS_LENGTH = 32;\n/// @dev The amount of discarded last bits when encoding tip values\nuint256 constant TIPS_GRANULARITY = 32;\n/// @dev Tip values could be only the multiples of TIPS_MULTIPLIER\nuint256 constant TIPS_MULTIPLIER = 1 \u003c\u003c TIPS_GRANULARITY;\n// ══════════════════════════════ STATEMENT SALTS ══════════════════════════════\n/// @dev Salts for signing various statements\nbytes32 constant ATTESTATION_VALID_SALT = keccak256(\"ATTESTATION_VALID_SALT\");\nbytes32 constant ATTESTATION_INVALID_SALT = keccak256(\"ATTESTATION_INVALID_SALT\");\nbytes32 constant RECEIPT_VALID_SALT = keccak256(\"RECEIPT_VALID_SALT\");\nbytes32 constant RECEIPT_INVALID_SALT = keccak256(\"RECEIPT_INVALID_SALT\");\nbytes32 constant SNAPSHOT_VALID_SALT = keccak256(\"SNAPSHOT_VALID_SALT\");\nbytes32 constant STATE_INVALID_SALT = keccak256(\"STATE_INVALID_SALT\");\n// ═════════════════════════════════ PROTOCOL ══════════════════════════════════\n/// @dev Optimistic period for new agent roots in LightManager\nuint32 constant AGENT_ROOT_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Timeout between the agent root could be proposed and resolved in LightManager\nuint32 constant AGENT_ROOT_PROPOSAL_TIMEOUT = 12 hours;\nuint32 constant BONDING_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Amount of time that the Notary will not be considered active after they won a dispute\nuint32 constant DISPUTE_TIMEOUT_NOTARY = 12 hours;\n/// @dev Amount of time without fresh data from Notaries before contract owner can resolve stuck disputes manually\nuint256 constant FRESH_DATA_TIMEOUT = 4 hours;\n/// @dev Maximum bytes per message = 2 KiB (somewhat arbitrarily set to begin)\nuint256 constant MAX_CONTENT_BYTES = 2 * 2 ** 10;\n/// @dev Maximum value for the summit tip that could be set in GasOracle\nuint256 constant MAX_SUMMIT_TIP = 0.01 ether;\n\n// contracts/libs/Errors.sol\n\n// ══════════════════════════════ INVALID CALLER ═══════════════════════════════\n\nerror CallerNotAgentManager();\nerror CallerNotDestination();\nerror CallerNotInbox();\nerror CallerNotSummit();\n\n// ══════════════════════════════ INCORRECT DATA ═══════════════════════════════\n\nerror IncorrectAttestation();\nerror IncorrectAgentDomain();\nerror IncorrectAgentIndex();\nerror IncorrectAgentProof();\nerror IncorrectAgentRoot();\nerror IncorrectDataHash();\nerror IncorrectDestinationDomain();\nerror IncorrectOriginDomain();\nerror IncorrectSnapshotProof();\nerror IncorrectSnapshotRoot();\nerror IncorrectState();\nerror IncorrectStatesAmount();\nerror IncorrectTipsProof();\nerror IncorrectVersionLength();\n\nerror IncorrectNonce();\nerror IncorrectSender();\nerror IncorrectRecipient();\n\nerror FlagOutOfRange();\nerror IndexOutOfRange();\nerror NonceOutOfRange();\n\nerror OutdatedNonce();\n\nerror UnformattedAttestation();\nerror UnformattedAttestationReport();\nerror UnformattedBaseMessage();\nerror UnformattedCallData();\nerror UnformattedCallDataPrefix();\nerror UnformattedMessage();\nerror UnformattedReceipt();\nerror UnformattedReceiptReport();\nerror UnformattedSignature();\nerror UnformattedSnapshot();\nerror UnformattedState();\nerror UnformattedStateReport();\n\n// ═══════════════════════════════ MERKLE TREES ════════════════════════════════\n\nerror LeafNotProven();\nerror MerkleTreeFull();\nerror NotEnoughLeafs();\nerror TreeHeightTooLow();\n\n// ═════════════════════════════ OPTIMISTIC PERIOD ═════════════════════════════\n\nerror BaseClientOptimisticPeriod();\nerror MessageOptimisticPeriod();\nerror SlashAgentOptimisticPeriod();\nerror WithdrawTipsOptimisticPeriod();\nerror ZeroProofMaturity();\n\n// ═══════════════════════════════ AGENT MANAGER ═══════════════════════════════\n\nerror AgentNotGuard();\nerror AgentNotNotary();\n\nerror AgentCantBeAdded();\nerror AgentNotActive();\nerror AgentNotActiveNorUnstaking();\nerror AgentNotFraudulent();\nerror AgentNotUnstaking();\nerror AgentUnknown();\n\nerror AgentRootNotProposed();\nerror AgentRootTimeoutNotOver();\n\nerror NotStuck();\n\nerror DisputeAlreadyResolved();\nerror DisputeNotOpened();\nerror DisputeTimeoutNotOver();\nerror GuardInDispute();\nerror NotaryInDispute();\n\nerror MustBeSynapseDomain();\nerror SynapseDomainForbidden();\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\nerror AlreadyExecuted();\nerror AlreadyFailed();\nerror DuplicatedSnapshotRoot();\nerror IncorrectMagicValue();\nerror GasLimitTooLow();\nerror GasSuppliedTooLow();\n\n// ══════════════════════════════════ ORIGIN ═══════════════════════════════════\n\nerror ContentLengthTooBig();\nerror EthTransferFailed();\nerror InsufficientEthBalance();\n\n// ════════════════════════════════ GAS ORACLE ═════════════════════════════════\n\nerror LocalGasDataNotSet();\nerror RemoteGasDataNotSet();\n\n// ═══════════════════════════════════ TIPS ════════════════════════════════════\n\nerror SummitTipTooHigh();\nerror TipsClaimMoreThanEarned();\nerror TipsClaimZero();\nerror TipsOverflow();\nerror TipsValueTooLow();\n\n// ════════════════════════════════ MEMORY VIEW ════════════════════════════════\n\nerror IndexedTooMuch();\nerror ViewOverrun();\nerror OccupiedMemory();\nerror UnallocatedMemory();\nerror PrecompileOutOfGas();\n\n// ═════════════════════════════════ MULTICALL ═════════════════════════════════\n\nerror MulticallFailed();\n\n// contracts/libs/TypeCasts.sol\n\nlibrary TypeCasts {\n    // alignment preserving cast\n    function addressToBytes32(address addr) internal pure returns (bytes32) {\n        return bytes32(uint256(uint160(addr)));\n    }\n\n    // alignment preserving cast\n    function bytes32ToAddress(bytes32 buf) internal pure returns (address) {\n        return address(uint160(uint256(buf)));\n    }\n}\n\n// contracts/libs/stack/Number.sol\n\n/// Number is a compact representation of uint256, that is fit into 16 bits\n/// with the maximum relative error under 0.4%.\ntype Number is uint16;\n\nusing NumberLib for Number global;\n\n/// # Number\n/// Library for compact representation of uint256 numbers.\n/// - Number is stored using mantissa and exponent, each occupying 8 bits.\n/// - Numbers under 2**8 are stored as `mantissa` with `exponent = 0xFF`.\n/// - Numbers at least 2**8 are approximated as `(256 + mantissa) \u003c\u003c exponent`\n/// \u003e - `0 \u003c= mantissa \u003c 256`\n/// \u003e - `0 \u003c= exponent \u003c= 247` (`256 * 2**248` doesn't fit into uint256)\n/// # Number stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type  | Bytes |\n/// | ---------- | -------- | ----- | ----- |\n/// | (002..001] | mantissa | uint8 | 1     |\n/// | (001..000] | exponent | uint8 | 1     |\n\nlibrary NumberLib {\n    /// @dev Amount of bits to shift to mantissa field\n    uint16 private constant SHIFT_MANTISSA = 8;\n\n    /// @notice For bwad math (binary wad) we use 2**64 as \"wad\" unit.\n    /// @dev We are using not using 10**18 as wad, because it is not stored precisely in NumberLib.\n    uint256 internal constant BWAD_SHIFT = 64;\n    uint256 internal constant BWAD = 1 \u003c\u003c BWAD_SHIFT;\n    /// @notice ~0.1% in bwad units.\n    uint256 internal constant PER_MILLE_SHIFT = BWAD_SHIFT - 10;\n    uint256 internal constant PER_MILLE = 1 \u003c\u003c PER_MILLE_SHIFT;\n\n    /// @notice Compresses uint256 number into 16 bits.\n    function compress(uint256 value) internal pure returns (Number) {\n        // Find `msb` such as `2**msb \u003c= value \u003c 2**(msb + 1)`\n        uint256 msb = mostSignificantBit(value);\n        // We want to preserve 9 bits of precision.\n        // The highest bit is always 1, so we can skip it.\n        // The remaining 8 highest bits are stored as mantissa.\n        if (msb \u003c 8) {\n            // Value is less than 2**8, so we can use value as mantissa with \"-1\" exponent.\n            return _encode(uint8(value), 0xFF);\n        } else {\n            // We use `msb - 8` as exponent otherwise. Note that `exponent \u003e= 0`.\n            unchecked {\n                uint256 exponent = msb - 8;\n                // Shifting right by `msb-8` bits will shift the \"remaining 8 highest bits\" into the 8 lowest bits.\n                // uint8() will truncate the highest bit.\n                return _encode(uint8(value \u003e\u003e exponent), uint8(exponent));\n            }\n        }\n    }\n\n    /// @notice Decompresses 16 bits number into uint256.\n    /// @dev The outcome is an approximation of the original number: `(value - value / 256) \u003c number \u003c= value`.\n    function decompress(Number number) internal pure returns (uint256 value) {\n        // Isolate 8 highest bits as the mantissa.\n        uint256 mantissa = Number.unwrap(number) \u003e\u003e SHIFT_MANTISSA;\n        // This will truncate the highest bits, leaving only the exponent.\n        uint256 exponent = uint8(Number.unwrap(number));\n        if (exponent == 0xFF) {\n            return mantissa;\n        } else {\n            unchecked {\n                return (256 + mantissa) \u003c\u003c (exponent);\n            }\n        }\n    }\n\n    /// @dev Returns the most significant bit of `x`\n    /// https://solidity-by-example.org/bitwise/\n    function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\n        // To find `msb` we determine it bit by bit, starting from the highest one.\n        // `0 \u003c= msb \u003c= 255`, so we start from the highest bit, 1\u003c\u003c7 == 128.\n        // If `x` is at least 2**128, then the highest bit of `x` is at least 128.\n        // solhint-disable no-inline-assembly\n        assembly {\n            // `f` is set to 1\u003c\u003c7 if `x \u003e= 2**128` and to 0 otherwise.\n            let f := shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\n            // If `x \u003e= 2**128` then set `msb` highest bit to 1 and shift `x` right by 128.\n            // Otherwise, `msb` remains 0 and `x` remains unchanged.\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        // `x` is now at most 2**128 - 1. Continue the same way, the next highest bit is 1\u003c\u003c6 == 64.\n        assembly {\n            // `f` is set to 1\u003c\u003c6 if `x \u003e= 2**64` and to 0 otherwise.\n            let f := shl(6, gt(x, 0xFFFFFFFFFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c5 if `x \u003e= 2**32` and to 0 otherwise.\n            let f := shl(5, gt(x, 0xFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c4 if `x \u003e= 2**16` and to 0 otherwise.\n            let f := shl(4, gt(x, 0xFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c3 if `x \u003e= 2**8` and to 0 otherwise.\n            let f := shl(3, gt(x, 0xFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c2 if `x \u003e= 2**4` and to 0 otherwise.\n            let f := shl(2, gt(x, 0xF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c1 if `x \u003e= 2**2` and to 0 otherwise.\n            let f := shl(1, gt(x, 0x3))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1 if `x \u003e= 2**1` and to 0 otherwise.\n            let f := gt(x, 0x1)\n            msb := or(msb, f)\n        }\n    }\n\n    /// @dev Wraps (mantissa, exponent) pair into Number.\n    function _encode(uint8 mantissa, uint8 exponent) private pure returns (Number) {\n        // Casts below are upcasts, so they are safe.\n        return Number.wrap(uint16(mantissa) \u003c\u003c SHIFT_MANTISSA | uint16(exponent));\n    }\n}\n\n// contracts/libs/stack/Request.sol\n\n/// Request is encoded data with \"message execution request\".\ntype Request is uint192;\n\nusing RequestLib for Request global;\n\n/// Library for formatting _the request part_ of _the base messages_.\n/// - Request represents a message sender requirements for the message execution on the destination chain.\n/// - Request occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n/// \u003e gasDrop field is included for future compatibility and is ignored at the moment.\n///\n/// # Request stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type   | Bytes | Description                                          |\n/// | ---------- | -------- | ------ | ----- | ---------------------------------------------------- |\n/// | (024..012] | gasDrop  | uint96 | 12    | Minimum amount of gas token to drop to the recipient |\n/// | (012..004] | gasLimit | uint64 | 8     | Minimum amount of gas units to supply for execution  |\n/// | (004..000] | version  | uint32 | 4     | Base message version to pass to the recipient        |\n\nlibrary RequestLib {\n    /// @dev Amount of bits to shift to gasDrop field\n    uint192 private constant SHIFT_GAS_DROP = 12 * 8;\n    /// @dev Amount of bits to shift to gasLimit field\n    uint192 private constant SHIFT_GAS_LIMIT = 4 * 8;\n\n    /// @notice Returns an encoded request with the given fields\n    /// @param gasDrop_     Minimum amount of gas token to drop to the recipient (ignored at the moment)\n    /// @param gasLimit_    Minimum amount of gas units to supply for execution\n    /// @param version_     Base message version to pass to the recipient\n    function encodeRequest(uint96 gasDrop_, uint64 gasLimit_, uint32 version_) internal pure returns (Request) {\n        // Casts below are upcasts, so they are safe\n        return Request.wrap(uint192(gasDrop_) \u003c\u003c SHIFT_GAS_DROP | uint192(gasLimit_) \u003c\u003c SHIFT_GAS_LIMIT | version_);\n    }\n\n    /// @notice Wraps the padded encoded request into a Request-typed value.\n    /// @dev The \"padded\" request is simply an encoded request casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded requests\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedRequest) internal pure returns (Request) {\n        // Casting to uint192 will truncate the highest bits, which is the behavior we want\n        return Request.wrap(uint192(paddedRequest));\n    }\n\n    /// @notice Returns the requested of gas token to drop to the recipient.\n    function gasDrop(Request request) internal pure returns (uint96) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return uint96(Request.unwrap(request) \u003e\u003e SHIFT_GAS_DROP);\n    }\n\n    /// @notice Returns the requested minimum amount of gas units to supply for execution.\n    function gasLimit(Request request) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Request.unwrap(request) \u003e\u003e SHIFT_GAS_LIMIT);\n    }\n\n    /// @notice Returns the requested base message version to pass to the recipient.\n    function version(Request request) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Request.unwrap(request));\n    }\n}\n\n// node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        require(value \u003c= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        require(value \u003c= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        require(value \u003c= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value \u003c= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        require(value \u003c= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        require(value \u003c= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        require(value \u003c= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        require(value \u003c= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        require(value \u003c= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        require(value \u003c= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        require(value \u003c= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        require(value \u003c= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        require(value \u003c= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        require(value \u003c= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        require(value \u003c= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value \u003c= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        require(value \u003c= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        require(value \u003c= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        require(value \u003c= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value \u003c= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        require(value \u003c= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        require(value \u003c= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        require(value \u003c= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value \u003c= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        require(value \u003c= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        require(value \u003c= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        require(value \u003c= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value \u003c= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        require(value \u003c= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value \u003c= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value \u003c= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     *\n     * _Available since v3.0._\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value \u003e= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     *\n     * _Available since v3.0._\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value \u003c= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     *\n     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length \u003e 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance \u003e= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance \u003e= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length \u003e 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n\n// contracts/base/MultiCallable.sol\n\n/// @notice Collection of Multicall utilities. Fork of Multicall3:\n/// https://github.com/mds1/multicall/blob/master/src/Multicall3.sol\nabstract contract MultiCallable {\n    struct Call {\n        bool allowFailure;\n        bytes callData;\n    }\n\n    struct Result {\n        bool success;\n        bytes returnData;\n    }\n\n    /// @notice Aggregates a few calls to this contract into one multicall without modifying `msg.sender`.\n    function multicall(Call[] calldata calls) external returns (Result[] memory callResults) {\n        uint256 amount = calls.length;\n        callResults = new Result[](amount);\n        Call calldata call_;\n        for (uint256 i = 0; i \u003c amount;) {\n            call_ = calls[i];\n            Result memory result = callResults[i];\n            // We perform a delegate call to ourselves here. Delegate call does not modify `msg.sender`, so\n            // this will have the same effect as if `msg.sender` performed all the calls themselves one by one.\n            // solhint-disable-next-line avoid-low-level-calls\n            (result.success, result.returnData) = address(this).delegatecall(call_.callData);\n            // solhint-disable-next-line no-inline-assembly\n            assembly {\n                // Revert if the call fails and failure is not allowed\n                // `allowFailure := calldataload(call_)` and `success := mload(result)`\n                if iszero(or(calldataload(call_), mload(result))) {\n                    // Revert with `0x4d6a2328` (function selector for `MulticallFailed()`)\n                    mstore(0x00, 0x4d6a232800000000000000000000000000000000000000000000000000000000)\n                    revert(0x00, 0x04)\n                }\n            }\n            unchecked {\n                ++i;\n            }\n        }\n    }\n}\n\n// contracts/base/Version.sol\n\n/**\n * @title Versioned\n * @notice Version getter for contracts. Doesn't use any storage slots, meaning\n * it will never cause any troubles with the upgradeable contracts. For instance, this contract\n * can be added or removed from the inheritance chain without shifting the storage layout.\n */\nabstract contract Versioned {\n    /**\n     * @notice Struct that is mimicking the storage layout of a string with 32 bytes or less.\n     * Length is limited by 32, so the whole string payload takes two memory words:\n     * @param length    String length\n     * @param data      String characters\n     */\n    struct _ShortString {\n        uint256 length;\n        bytes32 data;\n    }\n\n    /// @dev Length of the \"version string\"\n    uint256 private immutable _length;\n    /// @dev Bytes representation of the \"version string\".\n    /// Strings with length over 32 are not supported!\n    bytes32 private immutable _data;\n\n    constructor(string memory version_) {\n        _length = bytes(version_).length;\n        if (_length \u003e 32) revert IncorrectVersionLength();\n        // bytes32 is left-aligned =\u003e this will store the byte representation of the string\n        // with the trailing zeroes to complete the 32-byte word\n        _data = bytes32(bytes(version_));\n    }\n\n    function version() external view returns (string memory versionString) {\n        // Load the immutable values to form the version string\n        _ShortString memory str = _ShortString(_length, _data);\n        // The only way to do this cast is doing some dirty assembly\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            versionString := str\n        }\n    }\n}\n\n// contracts/libs/ChainContext.sol\n\n/// @notice Library for accessing chain context variables as tightly packed integers.\n/// Messaging contracts should rely on this library for accessing chain context variables\n/// instead of doing the casting themselves.\nlibrary ChainContext {\n    using SafeCast for uint256;\n\n    /// @notice Returns the current block number as uint40.\n    /// @dev Reverts if block number is greater than 40 bits, which is not supposed to happen\n    /// until the block.timestamp overflows (assuming block time is at least 1 second).\n    function blockNumber() internal view returns (uint40) {\n        return block.number.toUint40();\n    }\n\n    /// @notice Returns the current block timestamp as uint40.\n    /// @dev Reverts if block timestamp is greater than 40 bits, which is\n    /// supposed to happen approximately in year 36835.\n    function blockTimestamp() internal view returns (uint40) {\n        return block.timestamp.toUint40();\n    }\n\n    /// @notice Returns the chain id as uint32.\n    /// @dev Reverts if chain id is greater than 32 bits, which is not\n    /// supposed to happen in production.\n    function chainId() internal view returns (uint32) {\n        return block.chainid.toUint32();\n    }\n}\n\n// contracts/libs/Structures.sol\n\n// Here we define common enums and structures to enable their easier reusing later.\n\n// ═══════════════════════════════ AGENT STATUS ════════════════════════════════\n\n/// @dev Potential statuses for the off-chain bonded agent:\n/// - Unknown: never provided a bond =\u003e signature not valid\n/// - Active: has a bond in BondingManager =\u003e signature valid\n/// - Unstaking: has a bond in BondingManager, initiated the unstaking =\u003e signature not valid\n/// - Resting: used to have a bond in BondingManager, successfully unstaked =\u003e signature not valid\n/// - Fraudulent: proven to commit fraud, value in Merkle Tree not updated =\u003e signature not valid\n/// - Slashed: proven to commit fraud, value in Merkle Tree was updated =\u003e signature not valid\n/// Unstaked agent could later be added back to THE SAME domain by staking a bond again.\n/// Honest agent: Unknown -\u003e Active -\u003e unstaking -\u003e Resting -\u003e Active ...\n/// Malicious agent: Unknown -\u003e Active -\u003e Fraudulent -\u003e Slashed\n/// Malicious agent: Unknown -\u003e Active -\u003e Unstaking -\u003e Fraudulent -\u003e Slashed\nenum AgentFlag {\n    Unknown,\n    Active,\n    Unstaking,\n    Resting,\n    Fraudulent,\n    Slashed\n}\n\n/// @notice Struct for storing an agent in the BondingManager contract.\nstruct AgentStatus {\n    AgentFlag flag;\n    uint32 domain;\n    uint32 index;\n}\n// 184 bits available for tight packing\n\nusing StructureUtils for AgentStatus global;\n\n/// @notice Potential statuses of an agent in terms of being in dispute\n/// - None: agent is not in dispute\n/// - Pending: agent is in unresolved dispute\n/// - Slashed: agent was in dispute that lead to agent being slashed\n/// Note: agent who won the dispute has their status reset to None\nenum DisputeFlag {\n    None,\n    Pending,\n    Slashed\n}\n\n/// @notice Struct for storing dispute status of an agent.\n/// @param flag         Dispute flag: None/Pending/Slashed.\n/// @param openedAt     Timestamp when the latest agent dispute was opened (zero if not opened).\n/// @param resolvedAt   Timestamp when the latest agent dispute was resolved (zero if not resolved).\nstruct DisputeStatus {\n    DisputeFlag flag;\n    uint40 openedAt;\n    uint40 resolvedAt;\n}\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\n/// @notice Struct representing the status of Destination contract.\n/// @param snapRootTime     Timestamp when latest snapshot root was accepted\n/// @param agentRootTime    Timestamp when latest agent root was accepted\n/// @param notaryIndex      Index of Notary who signed the latest agent root\nstruct DestinationStatus {\n    uint40 snapRootTime;\n    uint40 agentRootTime;\n    uint32 notaryIndex;\n}\n\n// ═══════════════════════════════ EXECUTION HUB ═══════════════════════════════\n\n/// @notice Potential statuses of the message in Execution Hub.\n/// - None: there hasn't been a valid attempt to execute the message yet\n/// - Failed: there was a valid attempt to execute the message, but recipient reverted\n/// - Success: there was a valid attempt to execute the message, and recipient did not revert\n/// Note: message can be executed until its status is Success\nenum MessageStatus {\n    None,\n    Failed,\n    Success\n}\n\nlibrary StructureUtils {\n    /// @notice Checks that Agent is Active\n    function verifyActive(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active) {\n            revert AgentNotActive();\n        }\n    }\n\n    /// @notice Checks that Agent is Unstaking\n    function verifyUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Unstaking) {\n            revert AgentNotUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Active or Unstaking\n    function verifyActiveUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active \u0026\u0026 status.flag != AgentFlag.Unstaking) {\n            revert AgentNotActiveNorUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Fraudulent\n    function verifyFraudulent(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Fraudulent) {\n            revert AgentNotFraudulent();\n        }\n    }\n\n    /// @notice Checks that Agent is not Unknown\n    function verifyKnown(AgentStatus memory status) internal pure {\n        if (status.flag == AgentFlag.Unknown) {\n            revert AgentUnknown();\n        }\n    }\n}\n\n// contracts/libs/memory/MemView.sol\n\n/// @dev MemView is an untyped view over a portion of memory to be used instead of `bytes memory`\ntype MemView is uint256;\n\n/// @dev Attach library functions to MemView\nusing MemViewLib for MemView global;\n\n/// @notice Library for operations with the memory views.\n/// Forked from https://github.com/summa-tx/memview-sol with several breaking changes:\n/// - The codebase is ported to Solidity 0.8\n/// - Custom errors are added\n/// - The runtime type checking is replaced with compile-time check provided by User-Defined Value Types\n///   https://docs.soliditylang.org/en/latest/types.html#user-defined-value-types\n/// - uint256 is used as the underlying type for the \"memory view\" instead of bytes29.\n///   It is wrapped into MemView custom type in order not to be confused with actual integers.\n/// - Therefore the \"type\" field is discarded, allowing to allocate 16 bytes for both view location and length\n/// - The documentation is expanded\n/// - Library functions unused by the rest of the codebase are removed\n//  - Very pretty code separators are added :)\nlibrary MemViewLib {\n    /// @notice Stack layout for uint256 (from highest bits to lowest)\n    /// (32 .. 16]      loc     16 bytes    Memory address of underlying bytes\n    /// (16 .. 00]      len     16 bytes    Length of underlying bytes\n\n    // ═══════════════════════════════════════════ BUILDING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Instantiate a new untyped memory view. This should generally not be called directly.\n     * Prefer `ref` wherever possible.\n     * @param loc_          The memory address\n     * @param len_          The length\n     * @return The new view with the specified location and length\n     */\n    function build(uint256 loc_, uint256 len_) internal pure returns (MemView) {\n        uint256 end_ = loc_ + len_;\n        // Make sure that a view is not constructed that points to unallocated memory\n        // as this could be indicative of a buffer overflow attack\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            if gt(end_, mload(0x40)) { end_ := 0 }\n        }\n        if (end_ == 0) {\n            revert UnallocatedMemory();\n        }\n        return _unsafeBuildUnchecked(loc_, len_);\n    }\n\n    /**\n     * @notice Instantiate a memory view from a byte array.\n     * @dev Note that due to Solidity memory representation, it is not possible to\n     * implement a deref, as the `bytes` type stores its len in memory.\n     * @param arr           The byte array\n     * @return The memory view over the provided byte array\n     */\n    function ref(bytes memory arr) internal pure returns (MemView) {\n        uint256 len_ = arr.length;\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 loc_;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // We add 0x20, so that the view starts exactly where the array data starts\n            loc_ := add(arr, 0x20)\n        }\n        return build(loc_, len_);\n    }\n\n    // ════════════════════════════════════════════ CLONING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to the new memory.\n     * @param memView       The memory view\n     * @return arr          The cloned byte array\n     */\n    function clone(MemView memView) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        unchecked {\n            _unsafeCopyTo(memView, ptr + 0x20);\n        }\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 len_ = memView.len();\n        uint256 footprint_ = memView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    /**\n     * @notice Copies all views, joins them into a new bytearray.\n     * @param memViews      The memory views\n     * @return arr          The new byte array with joined data behind the given views\n     */\n    function join(MemView[] memory memViews) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        MemView newView;\n        unchecked {\n            newView = _unsafeJoin(memViews, ptr + 0x20);\n        }\n        uint256 len_ = newView.len();\n        uint256 footprint_ = newView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    // ══════════════════════════════════════════ INSPECTING MEMORY VIEW ═══════════════════════════════════════════════\n\n    /**\n     * @notice Returns the memory address of the underlying bytes.\n     * @param memView       The memory view\n     * @return loc_         The memory address\n     */\n    function loc(MemView memView) internal pure returns (uint256 loc_) {\n        // loc is stored in the highest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u003e\u003e 128;\n    }\n\n    /**\n     * @notice Returns the number of bytes of the view.\n     * @param memView       The memory view\n     * @return len_         The length of the view\n     */\n    function len(MemView memView) internal pure returns (uint256 len_) {\n        // len is stored in the lowest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u0026 type(uint128).max;\n    }\n\n    /**\n     * @notice Returns the endpoint of `memView`.\n     * @param memView       The memory view\n     * @return end_         The endpoint of `memView`\n     */\n    function end(MemView memView) internal pure returns (uint256 end_) {\n        // The endpoint never overflows uint128, let alone uint256, so we could use unchecked math here\n        unchecked {\n            return memView.loc() + memView.len();\n        }\n    }\n\n    /**\n     * @notice Returns the number of memory words this memory view occupies, rounded up.\n     * @param memView       The memory view\n     * @return words_       The number of memory words\n     */\n    function words(MemView memView) internal pure returns (uint256 words_) {\n        // returning ceil(length / 32.0)\n        unchecked {\n            return (memView.len() + 31) \u003e\u003e 5;\n        }\n    }\n\n    /**\n     * @notice Returns the in-memory footprint of a fresh copy of the view.\n     * @param memView       The memory view\n     * @return footprint_   The in-memory footprint of a fresh copy of the view.\n     */\n    function footprint(MemView memView) internal pure returns (uint256 footprint_) {\n        // words() * 32\n        return memView.words() \u003c\u003c 5;\n    }\n\n    // ════════════════════════════════════════════ HASHING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the keccak256 hash of the underlying memory\n     * @param memView       The memory view\n     * @return digest       The keccak256 hash of the underlying memory\n     */\n    function keccak(MemView memView) internal pure returns (bytes32 digest) {\n        uint256 loc_ = memView.loc();\n        uint256 len_ = memView.len();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            digest := keccak256(loc_, len_)\n        }\n    }\n\n    /**\n     * @notice Adds a salt to the keccak256 hash of the underlying data and returns the keccak256 hash of the\n     * resulting data.\n     * @param memView       The memory view\n     * @return digestSalted keccak256(salt, keccak256(memView))\n     */\n    function keccakSalted(MemView memView, bytes32 salt) internal pure returns (bytes32 digestSalted) {\n        return keccak256(bytes.concat(salt, memView.keccak()));\n    }\n\n    // ════════════════════════════════════════════ SLICING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Safe slicing without memory modification.\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the given index\n     */\n    function slice(MemView memView, uint256 index_, uint256 len_) internal pure returns (MemView) {\n        uint256 loc_ = memView.loc();\n        // Ensure it doesn't overrun the view\n        if (loc_ + index_ + len_ \u003e memView.end()) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // loc_ + index_ \u003c= memView.end()\n            return build({loc_: loc_ + index_, len_: len_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing bytes from `index` to end(memView).\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @return The new view for the slice starting from the given index until the initial view endpoint\n     */\n    function sliceFrom(MemView memView, uint256 index_) internal pure returns (MemView) {\n        uint256 len_ = memView.len();\n        // Ensure it doesn't overrun the view\n        if (index_ \u003e len_) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // index_ \u003c= len_ =\u003e memView.loc() + index_ \u003c= memView.loc() + memView.len() == memView.end()\n            return build({loc_: memView.loc() + index_, len_: len_ - index_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the first `len` bytes.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the initial view beginning\n     */\n    function prefix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        return memView.slice({index_: 0, len_: len_});\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the last `len` byte.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length until the initial view endpoint\n     */\n    function postfix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        uint256 viewLen = memView.len();\n        // Ensure it doesn't overrun the view\n        if (len_ \u003e viewLen) {\n            revert ViewOverrun();\n        }\n        // Could do the unchecked math due to the check above\n        uint256 index_;\n        unchecked {\n            index_ = viewLen - len_;\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // len_ \u003c= memView.len() =\u003e memView.loc() \u003c= loc_ \u003c= memView.end()\n            return build({loc_: memView.loc() + viewLen - len_, len_: len_});\n        }\n    }\n\n    // ═══════════════════════════════════════════ INDEXING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Load up to 32 bytes from the view onto the stack.\n     * @dev Returns a bytes32 with only the `bytes_` HIGHEST bytes set.\n     * This can be immediately cast to a smaller fixed-length byte array.\n     * To automatically cast to an integer, use `indexUint`.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return result       The 32 byte result having only `bytes_` highest bytes set\n     */\n    function index(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (bytes32 result) {\n        if (bytes_ == 0) {\n            return bytes32(0);\n        }\n        // Can't load more than 32 bytes to the stack in one go\n        if (bytes_ \u003e 32) {\n            revert IndexedTooMuch();\n        }\n        // The last indexed byte should be within view boundaries\n        if (index_ + bytes_ \u003e memView.len()) {\n            revert ViewOverrun();\n        }\n        uint256 bitLength = bytes_ \u003c\u003c 3; // bytes_ * 8\n        uint256 loc_ = memView.loc();\n        // Get a mask with `bitLength` highest bits set\n        uint256 mask;\n        // 0x800...00 binary representation is 100...00\n        // sar stands for \"signed arithmetic shift\": https://en.wikipedia.org/wiki/Arithmetic_shift\n        // sar(N-1, 100...00) = 11...100..00, with exactly N highest bits set to 1\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            mask := sar(sub(bitLength, 1), 0x8000000000000000000000000000000000000000000000000000000000000000)\n        }\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load a full word using index offset, and apply mask to ignore non-relevant bytes\n            result := and(mload(add(loc_, index_)), mask)\n        }\n    }\n\n    /**\n     * @notice Parse an unsigned integer from the view at `index`.\n     * @dev Requires that the view have \u003e= `bytes_` bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return The unsigned integer\n     */\n    function indexUint(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (uint256) {\n        bytes32 indexedBytes = memView.index(index_, bytes_);\n        // `index()` returns left-aligned `bytes_`, while integers are right-aligned\n        // Shifting here to right-align with the full 32 bytes word: need to shift right `(32 - bytes_)` bytes\n        unchecked {\n            // memView.index() reverts when bytes_ \u003e 32, thus unchecked math\n            return uint256(indexedBytes) \u003e\u003e ((32 - bytes_) \u003c\u003c 3);\n        }\n    }\n\n    /**\n     * @notice Parse an address from the view at `index`.\n     * @dev Requires that the view have \u003e= 20 bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @return The address\n     */\n    function indexAddress(MemView memView, uint256 index_) internal pure returns (address) {\n        // index 20 bytes as `uint160`, and then cast to `address`\n        return address(uint160(memView.indexUint(index_, 20)));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns a memory view over the specified memory location\n    /// without checking if it points to unallocated memory.\n    function _unsafeBuildUnchecked(uint256 loc_, uint256 len_) private pure returns (MemView) {\n        // There is no scenario where loc or len would overflow uint128, so we omit this check.\n        // We use the highest 128 bits to encode the location and the lowest 128 bits to encode the length.\n        return MemView.wrap((loc_ \u003c\u003c 128) | len_);\n    }\n\n    /**\n     * @notice Copy the view to a location, return an unsafe memory reference\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memView       The memory view\n     * @param newLoc        The new location to copy the underlying view data\n     * @return The memory view over the unsafe memory with the copied underlying data\n     */\n    function _unsafeCopyTo(MemView memView, uint256 newLoc) private view returns (MemView) {\n        uint256 len_ = memView.len();\n        uint256 oldLoc = memView.loc();\n\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (newLoc \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        bool res;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // use the identity precompile (0x04) to copy\n            res := staticcall(gas(), 0x04, oldLoc, len_, newLoc, len_)\n        }\n        if (!res) revert PrecompileOutOfGas();\n        return _unsafeBuildUnchecked({loc_: newLoc, len_: len_});\n    }\n\n    /**\n     * @notice Join the views in memory, return an unsafe reference to the memory.\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memViews      The memory views\n     * @return The conjoined view pointing to the new memory\n     */\n    function _unsafeJoin(MemView[] memory memViews, uint256 location) private view returns (MemView) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (location \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        // Copy the views to the specified location one by one, by tracking the amount of copied bytes so far\n        uint256 offset = 0;\n        for (uint256 i = 0; i \u003c memViews.length;) {\n            MemView memView = memViews[i];\n            // We can use the unchecked math here as location + sum(view.length) will never overflow uint256\n            unchecked {\n                _unsafeCopyTo(memView, location + offset);\n                offset += memView.len();\n                ++i;\n            }\n        }\n        return _unsafeBuildUnchecked({loc_: location, len_: offset});\n    }\n}\n\n// contracts/libs/merkle/MerkleMath.sol\n\nlibrary MerkleMath {\n    // ═════════════════════════════════════════ BASIC MERKLE CALCULATIONS ═════════════════════════════════════════════\n\n    /**\n     * @notice Calculates the merkle root for the given leaf and merkle proof.\n     * @dev Will revert if proof length exceeds the tree height.\n     * @param index     Index of `leaf` in tree\n     * @param leaf      Leaf of the merkle tree\n     * @param proof     Proof of inclusion of `leaf` in the tree\n     * @param height    Height of the merkle tree\n     * @return root_    Calculated Merkle Root\n     */\n    function proofRoot(uint256 index, bytes32 leaf, bytes32[] memory proof, uint256 height)\n        internal\n        pure\n        returns (bytes32 root_)\n    {\n        // Proof length could not exceed the tree height\n        uint256 proofLen = proof.length;\n        if (proofLen \u003e height) revert TreeHeightTooLow();\n        root_ = leaf;\n        /// @dev Apply unchecked to all ++h operations\n        unchecked {\n            // Go up the tree levels from the leaf following the proof\n            for (uint256 h = 0; h \u003c proofLen; ++h) {\n                // Get a sibling node on current level: this is proof[h]\n                root_ = getParent(root_, proof[h], index, h);\n            }\n            // Go up to the root: the remaining siblings are EMPTY\n            for (uint256 h = proofLen; h \u003c height; ++h) {\n                root_ = getParent(root_, bytes32(0), index, h);\n            }\n        }\n    }\n\n    /**\n     * @notice Calculates the parent of a node on the path from one of the leafs to root.\n     * @param node          Node on a path from tree leaf to root\n     * @param sibling       Sibling for a given node\n     * @param leafIndex     Index of the tree leaf\n     * @param nodeHeight    \"Level height\" for `node` (ZERO for leafs, ORIGIN_TREE_HEIGHT for root)\n     */\n    function getParent(bytes32 node, bytes32 sibling, uint256 leafIndex, uint256 nodeHeight)\n        internal\n        pure\n        returns (bytes32 parent)\n    {\n        // Index for `node` on its \"tree level\" is (leafIndex / 2**height)\n        // \"Left child\" has even index, \"right child\" has odd index\n        if ((leafIndex \u003e\u003e nodeHeight) \u0026 1 == 0) {\n            // Left child\n            return getParent(node, sibling);\n        } else {\n            // Right child\n            return getParent(sibling, node);\n        }\n    }\n\n    /// @notice Calculates the parent of tow nodes in the merkle tree.\n    /// @dev We use implementation with H(0,0) = 0\n    /// This makes EVERY empty node in the tree equal to ZERO,\n    /// saving us from storing H(0,0), H(H(0,0), H(0, 0)), and so on\n    /// @param leftChild    Left child of the calculated node\n    /// @param rightChild   Right child of the calculated node\n    /// @return parent      Value for the node having above mentioned children\n    function getParent(bytes32 leftChild, bytes32 rightChild) internal pure returns (bytes32 parent) {\n        if (leftChild == bytes32(0) \u0026\u0026 rightChild == bytes32(0)) {\n            return 0;\n        } else {\n            return keccak256(bytes.concat(leftChild, rightChild));\n        }\n    }\n\n    // ════════════════════════════════ ROOT/PROOF CALCULATION FOR A LIST OF LEAFS ═════════════════════════════════════\n\n    /**\n     * @notice Calculates merkle root for a list of given leafs.\n     * Merkle Tree is constructed by padding the list with ZERO values for leafs until list length is `2**height`.\n     * Merkle Root is calculated for the constructed tree, and then saved in `leafs[0]`.\n     * \u003e Note:\n     * \u003e - `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * \u003e - Caller is expected not to reuse `hashes` list after the call, and only use `leafs[0]` value,\n     * which is guaranteed to contain the calculated merkle root.\n     * \u003e - root is calculated using the `H(0,0) = 0` Merkle Tree implementation. See MerkleTree.sol for details.\n     * @dev Amount of leaves should be at most `2**height`\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param height    Height of the Merkle Tree to construct\n     */\n    function calculateRoot(bytes32[] memory hashes, uint256 height) internal pure {\n        uint256 levelLength = hashes.length;\n        // Amount of hashes could not exceed amount of leafs in tree with the given height\n        if (levelLength \u003e (1 \u003c\u003c height)) revert TreeHeightTooLow();\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\": the amount of iterations for the for loop above.\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n            }\n        }\n    }\n\n    /**\n     * @notice Generates a proof of inclusion of a leaf in the list. If the requested index is outside\n     * of the list range, generates a proof of inclusion for an empty leaf (proof of non-inclusion).\n     * The Merkle Tree is constructed by padding the list with ZERO values until list length is a power of two\n     * __AND__ index is in the extended list range. For example:\n     *  - `hashes.length == 6` and `0 \u003c= index \u003c= 7` will \"extend\" the list to 8 entries.\n     *  - `hashes.length == 6` and `7 \u003c index \u003c= 15` will \"extend\" the list to 16 entries.\n     * \u003e Note: `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * Caller is expected not to reuse `hashes` list after the call.\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param index     Leaf index to generate the proof for\n     * @return proof    Generated merkle proof\n     */\n    function calculateProof(bytes32[] memory hashes, uint256 index) internal pure returns (bytes32[] memory proof) {\n        // Use only meaningful values for the shortened proof\n        // Check if index is within the list range (we want to generates proofs for outside leafs as well)\n        uint256 height = getHeight(index \u003c hashes.length ? hashes.length : (index + 1));\n        proof = new bytes32[](height);\n        uint256 levelLength = hashes.length;\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Use sibling for the merkle proof; `index^1` is index of our sibling\n                proof[h] = (index ^ 1 \u003c levelLength) ? hashes[index ^ 1] : bytes32(0);\n\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\"\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n                // Traverse to parent node\n                index \u003e\u003e= 1;\n            }\n        }\n    }\n\n    /// @notice Returns the height of the tree having a given amount of leafs.\n    function getHeight(uint256 leafs) internal pure returns (uint256 height) {\n        uint256 amount = 1;\n        while (amount \u003c leafs) {\n            unchecked {\n                ++height;\n            }\n            amount \u003c\u003c= 1;\n        }\n    }\n}\n\n// contracts/libs/stack/GasData.sol\n\n/// GasData in encoded data with \"basic information about gas prices\" for some chain.\ntype GasData is uint96;\n\nusing GasDataLib for GasData global;\n\n/// ChainGas is encoded data with given chain's \"basic information about gas prices\".\ntype ChainGas is uint128;\n\nusing GasDataLib for ChainGas global;\n\n/// Library for encoding and decoding GasData and ChainGas structs.\n/// # GasData\n/// `GasData` is a struct to store the \"basic information about gas prices\", that could\n/// be later used to approximate the cost of a message execution, and thus derive the\n/// minimal tip values for sending a message to the chain.\n/// \u003e - `GasData` is supposed to be cached by `GasOracle` contract, allowing to store the\n/// \u003e approximates instead of the exact values, and thus save on storage costs.\n/// \u003e - For instance, if `GasOracle` only updates the values on +- 10% change, having an\n/// \u003e 0.4% error on the approximates would be acceptable.\n/// `GasData` is supposed to be included in the Origin's state, which are synced across\n/// chains using Agent-signed snapshots and attestations.\n/// ## GasData stack layout (from highest bits to lowest)\n///\n/// | Position   | Field        | Type   | Bytes | Description                                         |\n/// | ---------- | ------------ | ------ | ----- | --------------------------------------------------- |\n/// | (012..010] | gasPrice     | uint16 | 2     | Gas price for the chain (in Wei per gas unit)       |\n/// | (010..008] | dataPrice    | uint16 | 2     | Calldata price (in Wei per byte of content)         |\n/// | (008..006] | execBuffer   | uint16 | 2     | Tx fee safety buffer for message execution (in Wei) |\n/// | (006..004] | amortAttCost | uint16 | 2     | Amortized cost for attestation submission (in Wei)  |\n/// | (004..002] | etherPrice   | uint16 | 2     | Chain's Ether Price / Mainnet Ether Price (in BWAD) |\n/// | (002..000] | markup       | uint16 | 2     | Markup for the message execution (in BWAD)          |\n/// \u003e See Number.sol for more details on `Number` type and BWAD (binary WAD) math.\n///\n/// ## ChainGas stack layout (from highest bits to lowest)\n///\n/// | Position   | Field   | Type   | Bytes | Description      |\n/// | ---------- | ------- | ------ | ----- | ---------------- |\n/// | (016..004] | gasData | uint96 | 12    | Chain's gas data |\n/// | (004..000] | domain  | uint32 | 4     | Chain's domain   |\nlibrary GasDataLib {\n    /// @dev Amount of bits to shift to gasPrice field\n    uint96 private constant SHIFT_GAS_PRICE = 10 * 8;\n    /// @dev Amount of bits to shift to dataPrice field\n    uint96 private constant SHIFT_DATA_PRICE = 8 * 8;\n    /// @dev Amount of bits to shift to execBuffer field\n    uint96 private constant SHIFT_EXEC_BUFFER = 6 * 8;\n    /// @dev Amount of bits to shift to amortAttCost field\n    uint96 private constant SHIFT_AMORT_ATT_COST = 4 * 8;\n    /// @dev Amount of bits to shift to etherPrice field\n    uint96 private constant SHIFT_ETHER_PRICE = 2 * 8;\n\n    /// @dev Amount of bits to shift to gasData field\n    uint128 private constant SHIFT_GAS_DATA = 4 * 8;\n\n    // ═════════════════════════════════════════════════ GAS DATA ══════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded GasData struct with the given fields.\n    /// @param gasPrice_        Gas price for the chain (in Wei per gas unit)\n    /// @param dataPrice_       Calldata price (in Wei per byte of content)\n    /// @param execBuffer_      Tx fee safety buffer for message execution (in Wei)\n    /// @param amortAttCost_    Amortized cost for attestation submission (in Wei)\n    /// @param etherPrice_      Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n    /// @param markup_          Markup for the message execution (in BWAD)\n    function encodeGasData(\n        Number gasPrice_,\n        Number dataPrice_,\n        Number execBuffer_,\n        Number amortAttCost_,\n        Number etherPrice_,\n        Number markup_\n    ) internal pure returns (GasData) {\n        // Number type wraps uint16, so could safely be casted to uint96\n        // forgefmt: disable-next-item\n        return GasData.wrap(\n            uint96(Number.unwrap(gasPrice_)) \u003c\u003c SHIFT_GAS_PRICE |\n            uint96(Number.unwrap(dataPrice_)) \u003c\u003c SHIFT_DATA_PRICE |\n            uint96(Number.unwrap(execBuffer_)) \u003c\u003c SHIFT_EXEC_BUFFER |\n            uint96(Number.unwrap(amortAttCost_)) \u003c\u003c SHIFT_AMORT_ATT_COST |\n            uint96(Number.unwrap(etherPrice_)) \u003c\u003c SHIFT_ETHER_PRICE |\n            uint96(Number.unwrap(markup_))\n        );\n    }\n\n    /// @notice Wraps padded uint256 value into GasData struct.\n    function wrapGasData(uint256 paddedGasData) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(paddedGasData));\n    }\n\n    /// @notice Returns the gas price, in Wei per gas unit.\n    function gasPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_GAS_PRICE));\n    }\n\n    /// @notice Returns the calldata price, in Wei per byte of content.\n    function dataPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_DATA_PRICE));\n    }\n\n    /// @notice Returns the tx fee safety buffer for message execution, in Wei.\n    function execBuffer(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_EXEC_BUFFER));\n    }\n\n    /// @notice Returns the amortized cost for attestation submission, in Wei.\n    function amortAttCost(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_AMORT_ATT_COST));\n    }\n\n    /// @notice Returns the ratio of Chain's Ether Price / Mainnet Ether Price, in BWAD math.\n    function etherPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_ETHER_PRICE));\n    }\n\n    /// @notice Returns the markup for the message execution, in BWAD math.\n    function markup(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data)));\n    }\n\n    // ════════════════════════════════════════════════ CHAIN DATA ═════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded ChainGas struct with the given fields.\n    /// @param gasData_ Chain's gas data\n    /// @param domain_  Chain's domain\n    function encodeChainGas(GasData gasData_, uint32 domain_) internal pure returns (ChainGas) {\n        // GasData type wraps uint96, so could safely be casted to uint128\n        return ChainGas.wrap(uint128(GasData.unwrap(gasData_)) \u003c\u003c SHIFT_GAS_DATA | uint128(domain_));\n    }\n\n    /// @notice Wraps padded uint256 value into ChainGas struct.\n    function wrapChainGas(uint256 paddedChainGas) internal pure returns (ChainGas) {\n        // Casting to uint128 will truncate the highest bits, which is the behavior we want\n        return ChainGas.wrap(uint128(paddedChainGas));\n    }\n\n    /// @notice Returns the chain's gas data.\n    function gasData(ChainGas data) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(ChainGas.unwrap(data) \u003e\u003e SHIFT_GAS_DATA));\n    }\n\n    /// @notice Returns the chain's domain.\n    function domain(ChainGas data) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(ChainGas.unwrap(data));\n    }\n\n    /// @notice Returns the hash for the list of ChainGas structs.\n    function snapGasHash(ChainGas[] memory snapGas) internal pure returns (bytes32 snapGasHash_) {\n        // Use assembly to calculate the hash of the array without copying it\n        // ChainGas takes a single word of storage, thus ChainGas[] is stored in the following way:\n        // 0x00: length of the array, in words\n        // 0x20: first ChainGas struct\n        // 0x40: second ChainGas struct\n        // And so on...\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Find the location where the array data starts, we add 0x20 to skip the length field\n            let loc := add(snapGas, 0x20)\n            // Load the length of the array (in words).\n            // Shifting left 5 bits is equivalent to multiplying by 32: this converts from words to bytes.\n            let len := shl(5, mload(snapGas))\n            // Calculate the hash of the array\n            snapGasHash_ := keccak256(loc, len)\n        }\n    }\n}\n\n// contracts/libs/stack/Header.sol\n\n/// Header is encoded data with \"general routing information\".\ntype Header is uint136;\n\nusing HeaderLib for Header global;\n\n/// Types of messages supported by Origin-Destination\n/// - Base: message sent by protocol user, contains tips\n/// - Manager: message sent between AgentManager contracts located on different chains, no tips\nenum MessageFlag {\n    Base,\n    Manager\n}\n\nusing HeaderLib for MessageFlag global;\n\n/// Library for formatting _the header part_ of _the messages used by Origin and Destination_.\n/// - Header represents general information for routing a Message for Origin and Destination.\n/// - Header occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n///\n/// # Header stack layout (from highest bits to lowest)\n///\n/// | Position   | Field            | Type   | Bytes | Description                             |\n/// | ---------- | ---------------- | ------ | ----- | --------------------------------------- |\n/// | (017..016] | flag             | uint8  | 1     | Flag specifying the type of message     |\n/// | (016..012] | origin           | uint32 | 4     | Domain where message originated         |\n/// | (012..008] | nonce            | uint32 | 4     | Message nonce on the origin domain      |\n/// | (008..004] | destination      | uint32 | 4     | Domain where message will be executed   |\n/// | (004..000] | optimisticPeriod | uint32 | 4     | Optimistic period that will be enforced |\nlibrary HeaderLib {\n    /// @dev Amount of bits to shift to flag field\n    uint136 private constant SHIFT_FLAG = 16 * 8;\n    /// @dev Amount of bits to shift to origin field\n    uint136 private constant SHIFT_ORIGIN = 12 * 8;\n    /// @dev Amount of bits to shift to nonce field\n    uint136 private constant SHIFT_NONCE = 8 * 8;\n    /// @dev Amount of bits to shift to destination field\n    uint136 private constant SHIFT_DESTINATION = 4 * 8;\n\n    /// @notice Returns an encoded header with provided fields\n    /// @param origin_              Domain of origin chain\n    /// @param nonce_               Message nonce on origin chain\n    /// @param destination_         Domain of destination chain\n    /// @param optimisticPeriod_    Optimistic period for message execution\n    function encodeHeader(\n        MessageFlag flag_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint32 destination_,\n        uint32 optimisticPeriod_\n    ) internal pure returns (Header) {\n        // All casts below are upcasts, so they are safe\n        // forgefmt: disable-next-item\n        return Header.wrap(\n            uint136(uint8(flag_)) \u003c\u003c SHIFT_FLAG |\n            uint136(origin_) \u003c\u003c SHIFT_ORIGIN |\n            uint136(nonce_) \u003c\u003c SHIFT_NONCE |\n            uint136(destination_) \u003c\u003c SHIFT_DESTINATION |\n            uint136(optimisticPeriod_)\n        );\n    }\n\n    /// @notice Checks that the header is a valid encoded header.\n    function isHeader(uint256 paddedHeader) internal pure returns (bool) {\n        // Check that flag is within range\n        return _flag(paddedHeader) \u003c= uint8(type(MessageFlag).max);\n    }\n\n    /// @notice Wraps the padded encoded request into a Header-typed value.\n    /// @dev The \"padded\" header is simply an encoded header casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded headers\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedHeader) internal pure returns (Header) {\n        // Check that flag is within range\n        if (!isHeader(paddedHeader)) revert FlagOutOfRange();\n        // Casting to uint136 will truncate the highest bits, which is the behavior we want\n        return Header.wrap(uint136(paddedHeader));\n    }\n\n    /// @notice Returns header's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Header header) internal pure returns (bytes32 hashedHeader) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store header in scratch space\n            mstore(0, header)\n            // Compute hash of header padded to 32 bytes\n            hashedHeader := keccak256(0, 32)\n        }\n    }\n\n    // ══════════════════════════════════════════════ HEADER SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns header's flag field\n    function flag(Header header) internal pure returns (MessageFlag) {\n        // We check that flag is within range when wrapping the header, so this cast is safe\n        return MessageFlag(_flag(Header.unwrap(header)));\n    }\n\n    /// @notice Returns header's origin field\n    function origin(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_ORIGIN);\n    }\n\n    /// @notice Returns header's nonce field\n    function nonce(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_NONCE);\n    }\n\n    /// @notice Returns header's destination field\n    function destination(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_DESTINATION);\n    }\n\n    /// @notice Returns header's optimistic seconds field\n    function optimisticPeriod(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns header's flag field without casting to MessageFlag\n    function _flag(uint256 paddedHeader) private pure returns (uint8) {\n        // Casting to uint8 will truncate the highest bits, which is the behavior we want\n        return uint8(paddedHeader \u003e\u003e SHIFT_FLAG);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n     * constructor.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall \u0026\u0026 _initialized \u003c 1) || (!AddressUpgradeable.isContract(address(this)) \u0026\u0026 _initialized == 1),\n            \"Initializable: contract is already initialized\"\n        );\n        _initialized = 1;\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: setting the version to 255 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing \u0026\u0026 _initialized \u003c version, \"Initializable: contract is already initialized\");\n        _initialized = version;\n        _initializing = true;\n        _;\n        _initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        require(_initializing, \"Initializable: contract is not initializing\");\n        _;\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized != type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint8) {\n        return _initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _initializing;\n    }\n}\n\n// contracts/interfaces/IAgentManager.sol\n\ninterface IAgentManager {\n    /**\n     * @notice Allows Inbox to open a Dispute between a Guard and a Notary, if they are both not in Dispute already.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Guard or Notary is already in Dispute.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Allows Inbox to slash an agent, if their fraud was proven.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Domain doesn't match the saved agent domain.\n     * @param domain    Domain where the Agent is active\n     * @param agent     Address of the Agent\n     * @param prover    Address that initially provided fraud proof\n     */\n    function slashAgent(uint32 domain, address agent, address prover) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest known root of the Agent Merkle Tree.\n     */\n    function agentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns the number of opened Disputes.\n     * @dev This includes the Disputes that have been resolved already.\n     */\n    function getDisputesAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns information about the dispute with the given index.\n     * @dev Will revert if dispute with given index hasn't been opened yet.\n     * @param index             Dispute index\n     * @return guard            Address of the Guard in the Dispute\n     * @return notary           Address of the Notary in the Dispute\n     * @return slashedAgent     Address of the Agent who was slashed when Dispute was resolved\n     * @return fraudProver      Address who provided fraud proof to resolve the Dispute\n     * @return reportPayload    Raw payload with report data that led to the Dispute\n     * @return reportSignature  Guard signature for the report payload\n     */\n    function getDispute(uint256 index)\n        external\n        view\n        returns (\n            address guard,\n            address notary,\n            address slashedAgent,\n            address fraudProver,\n            bytes memory reportPayload,\n            bytes memory reportSignature\n        );\n\n    /**\n     * @notice Returns the current Dispute status of a given agent. See Structures.sol for details.\n     * @dev Every returned value will be set to zero if agent was not slashed and is not in Dispute.\n     * `rival` and `disputePtr` will be set to zero if the agent was slashed without being in Dispute.\n     * @param agent         Agent address\n     * @return flag         Flag describing the current Dispute status for the agent: None/Pending/Slashed\n     * @return rival        Address of the rival agent in the Dispute\n     * @return fraudProver  Address who provided fraud proof to resolve the Dispute\n     * @return disputePtr   Index of the opened Dispute PLUS ONE. Zero if agent is not in Dispute.\n     */\n    function disputeStatus(address agent)\n        external\n        view\n        returns (DisputeFlag flag, address rival, address fraudProver, uint256 disputePtr);\n}\n\n// contracts/interfaces/IAgentSecured.sol\n\ninterface IAgentSecured {\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * between a Guard and a Notary has been opened.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * has been resolved due to one of the agents being slashed.\n     * \u003e `rivalIndex` will be ZERO, if the slashed agent was not in the Dispute.\n     * @param slashedIndex  Index of the slashed agent in the Agent Merkle Tree\n     * @param rivalIndex    Index of the their Dispute Rival in the Agent Merkle Tree\n     */\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the address of the local AgentManager contract, which is treated as\n     * the \"source of truth\" for agent statuses.\n     */\n    function agentManager() external view returns (address);\n\n    /**\n     * @notice Returns the address of the local Inbox contract, which is treated as\n     * the \"source of truth\" for agent-signed statements.\n     * @dev Inbox passes verified agent statements to `IAgentSecured` contract.\n     */\n    function inbox() external view returns (address);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns (flag, openedAt, resolvedAt) that describes the latest status of\n     * the latest dispute for an agent with a given index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param agentIndex    Agent index in the Agent Merkle Tree\n     * @return              Latest dispute status for the given agent: (flag, openedAt, resolvedAt)\n     */\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory);\n}\n\n// contracts/libs/memory/ByteString.sol\n\n/// @dev CallData is a memory view over the payload to be used for an external call, i.e.\n/// recipient.call(callData). Its length is always (4 + 32 * N) bytes:\n/// - First 4 bytes represent the function selector.\n/// - 32 * N bytes represent N words that function arguments occupy.\ntype CallData is uint256;\n\n/// @dev Attach library functions to CallData\nusing ByteString for CallData global;\n\n/// @dev Signature is a memory view over a \"65 bytes\" array representing a ECDSA signature.\ntype Signature is uint256;\n\n/// @dev Attach library functions to Signature\nusing ByteString for Signature global;\n\nlibrary ByteString {\n    using MemViewLib for bytes;\n\n    /**\n     * @dev non-compact ECDSA signatures are enforced as of OZ 4.7.3\n     *\n     *      Signature payload memory layout\n     * [000 .. 032) r   bytes32 32 bytes\n     * [032 .. 064) s   bytes32 32 bytes\n     * [064 .. 065) v   uint8    1 byte\n     */\n    uint256 internal constant SIGNATURE_LENGTH = 65;\n    uint256 private constant OFFSET_R = 0;\n    uint256 private constant OFFSET_S = 32;\n    uint256 private constant OFFSET_V = 64;\n\n    /**\n     * @dev Calldata memory layout\n     * [000 .. 004) selector    bytes4  4 bytes\n     *      Optional: N function arguments\n     * [004 .. 036) arg1        bytes32 32 bytes\n     *      ..\n     * [AAA .. END) argN        bytes32 32 bytes\n     */\n    uint256 internal constant SELECTOR_LENGTH = 4;\n    uint256 private constant OFFSET_SELECTOR = 0;\n    uint256 private constant OFFSET_ARGUMENTS = SELECTOR_LENGTH;\n\n    // ═════════════════════════════════════════════════ SIGNATURE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the signature payload from the given values.\n     * @dev Using ByteString.formatSignature({r: r, s: s, v: v}) will make sure\n     * that params are given in the right order.\n     */\n    function formatSignature(bytes32 r, bytes32 s, uint8 v) internal pure returns (bytes memory) {\n        return abi.encodePacked(r, s, v);\n    }\n\n    /**\n     * @notice Returns a Signature view over for the given payload.\n     * @dev Will revert if the payload is not a signature.\n     */\n    function castToSignature(bytes memory payload) internal pure returns (Signature) {\n        return castToSignature(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Signature view.\n     * @dev Will revert if the memory view is not over a signature.\n     */\n    function castToSignature(MemView memView) internal pure returns (Signature) {\n        if (!isSignature(memView)) revert UnformattedSignature();\n        return Signature.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a signature\n     */\n    function isSignature(MemView memView) internal pure returns (bool) {\n        return memView.len() == SIGNATURE_LENGTH;\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Signature signature) internal pure returns (MemView) {\n        return MemView.wrap(Signature.unwrap(signature));\n    }\n\n    // ═════════════════════════════════════════════ SIGNATURE SLICING ═════════════════════════════════════════════════\n\n    /// @notice Unpacks signature payload into (r, s, v) parameters.\n    /// @dev Make sure to verify signature length with isSignature() beforehand.\n    function toRSV(Signature signature) internal pure returns (bytes32 r, bytes32 s, uint8 v) {\n        // Get the underlying memory view\n        MemView memView = unwrap(signature);\n        r = memView.index({index_: OFFSET_R, bytes_: 32});\n        s = memView.index({index_: OFFSET_S, bytes_: 32});\n        // Can be safely casted to uint8, since we index a single byte\n        v = uint8(memView.indexUint({index_: OFFSET_V, bytes_: 1}));\n    }\n\n    // ═════════════════════════════════════════════════ CALLDATA ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the calldata with the modified arguments:\n     * the existing arguments are prepended with the arguments from the prefix.\n     * @dev Given:\n     *  - `calldata = abi.encodeWithSelector(foo.selector, d, e);`\n     *  - `prefix = abi.encode(a, b, c);`\n     *  - `a`, `b`, `c` are arguments of static type (i.e. not dynamically sized ones)\n     *      Then:\n     *  - Function will return abi.encodeWithSelector(foo.selector, a, c, c, d, e)\n     *  - Returned calldata will trigger `foo(a, b, c, d, e)` when used for a contract call.\n     * Note: for clarification as to what types are considered static, see\n     * https://docs.soliditylang.org/en/latest/abi-spec.html#formal-specification-of-the-encoding\n     * @param callData  Calldata that needs to be modified\n     * @param prefix    ABI-encoded arguments to use as the first arguments in the new calldata\n     * @return Modified calldata having prefix as the first arguments.\n     */\n    function addPrefix(CallData callData, bytes memory prefix) internal view returns (bytes memory) {\n        // Prefix should occupy a whole amount of words in memory\n        if (!_fullWords(prefix.length)) revert UnformattedCallDataPrefix();\n        MemView[] memory views = new MemView[](3);\n        // Use payload's function selector\n        views[0] = abi.encodePacked(callData.callSelector()).ref();\n        // Use prefix as the first arguments\n        views[1] = prefix.ref();\n        // Use payload's remaining arguments\n        views[2] = callData.arguments();\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a CallData view over for the given payload.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(bytes memory payload) internal pure returns (CallData) {\n        return castToCallData(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a CallData view.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(MemView memView) internal pure returns (CallData) {\n        if (!isCallData(memView)) revert UnformattedCallData();\n        return CallData.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a valid calldata, i.e.\n     * a function selector, followed by arbitrary amount of arguments.\n     */\n    function isCallData(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Calldata should at least have a function selector\n        if (length \u003c SELECTOR_LENGTH) return false;\n        // The remainder of the calldata should be exactly N memory words (N \u003e= 0)\n        return _fullWords(length - SELECTOR_LENGTH);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(CallData callData) internal pure returns (MemView) {\n        return MemView.wrap(CallData.unwrap(callData));\n    }\n\n    /// @notice Returns callData's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(CallData callData) internal pure returns (bytes32) {\n        return callData.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ CALLDATA SLICING ══════════════════════════════════════════════════\n\n    /**\n     * @notice Returns amount of memory words (32 byte chunks) the function arguments\n     * occupy in the calldata.\n     * @dev This might differ from amount of arguments supplied, if any of the arguments\n     * occupies more than one memory slot. It is true, however, that argument part of the payload\n     * occupies exactly N words, even for dynamic types like `bytes`\n     */\n    function argumentWords(CallData callData) internal pure returns (uint256) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        // Equivalent of (length - SELECTOR_LENGTH) / 32\n        return (memView.len() - SELECTOR_LENGTH) \u003e\u003e 5;\n    }\n\n    /// @notice Returns selector for the provided calldata.\n    function callSelector(CallData callData) internal pure returns (bytes4) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return bytes4(memView.index({index_: OFFSET_SELECTOR, bytes_: SELECTOR_LENGTH}));\n    }\n\n    /// @notice Returns abi encoded arguments for the provided calldata.\n    function arguments(CallData callData) internal pure returns (MemView) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return memView.sliceFrom({index_: OFFSET_ARGUMENTS});\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if length is full amount of memory words (32 bytes).\n    function _fullWords(uint256 length) internal pure returns (bool) {\n        // The equivalent of length % 32 == 0\n        return length \u0026 31 == 0;\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n    function __Context_init() internal onlyInitializing {\n    }\n\n    function __Context_init_unchained() internal onlyInitializing {\n    }\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[50] private __gap;\n}\n\n// contracts/libs/merkle/MerkleTree.sol\n\n/// `BaseTree` is a struct representing incremental merkle tree.\n/// - Contains only the current branch.\n/// - The number of inserted leaves is stored externally, and is later supplied for tree operations.\n/// - Has a fixed height of `ORIGIN_TREE_HEIGHT`.\n/// - Can store up to `2 ** ORIGIN_TREE_HEIGHT - 1` leaves.\n/// \u003e Note: the hash function for the tree `H(x, y)` is defined as:\n/// \u003e - `H(0,0) = 0`\n/// \u003e - `H(x,y) = keccak256(x, y), when (x != 0 || y != 0)`\n/// ## Invariant for leafs\n/// - The leftmost empty leaf has `index == count`, where `count` is the amount of the inserted leafs so far.\n/// - Value for any empty leaf or node is bytes32(0).\n/// ## Invariant for current branch\n/// `branch[i]` is always the value of a node on the i-th level.\n/// Levels are numbered from leafs to root: `0 .. ORIGIN_TREE_HEIGHT`.\n/// `branch[i]` stores the value for the node, such that:\n//  - The node is a \"left child\" (e.g. has an even index).\n/// - The node must have two non-empty children.\n/// - Out of all level's \"left child\" nodes with \"non-empty children\",\n/// the one with the biggest index (the rightmost one) is stored as `branch[i]`.\n/// \u003e __`branch` could be used to form a proof of inclusion for the first empty leaf (`index == count`).__\n/// _Here is how:_\n/// - Let's walk along the path from the \"first empty leaf\" to the root.\n/// - i-th bit of the \"first empty leaf\" index (which is equal to `count`) determines if the path's node\n/// for this i-th level is a \"left child\" or a \"right child\".\n/// - i-th bit in `count` is 0 → we are the left child on this level → sibling is the right child\n/// that does not exist yet → `proof[i] = bytes32(0)`.\n/// - i-th bit in `count` is 1 → we are the right child on this level → sibling is the left child\n/// sibling is the rightmost \"left child\" node on the level → `proof[i] = branch[i]`.\n/// \u003e Therefore `proof[i] = (count \u0026 (1 \u003c\u003c i)) == 0 ? bytes32(0) : branch[i])`\nstruct BaseTree {\n    bytes32[ORIGIN_TREE_HEIGHT] branch;\n}\n\nusing MerkleTree for BaseTree global;\n\n/// `HistoricalTree` is an incremental merkle tree keeping track of its historical merkle roots.\n/// \u003e - `roots[N]` is the root of the tree after `N` leafs were inserted\n/// \u003e - `roots[0] == bytes32(0)`\n/// @param tree     Incremental merkle tree\n/// @param roots    Historical merkle roots of the tree\nstruct HistoricalTree {\n    BaseTree tree;\n    bytes32[] roots;\n}\n\nusing MerkleTree for HistoricalTree global;\n\n/// `DynamicTree` is a struct representing a Merkle Tree with `2**AGENT_TREE_HEIGHT` leaves.\n/// - A single operation is available: update value for leaf with an arbitrary index (which might be a non-empty leaf).\n/// - This is done by requesting the proof of inclusion for the old value, which is used to both\n/// verify the old value, and calculate the new root.\n/// \u003e Based on Original idea from [ER forum post](https://ethresear.ch/t/efficient-on-chain-dynamic-merkle-tree/11054).\nstruct DynamicTree {\n    bytes32 root;\n}\n\nusing MerkleTree for DynamicTree global;\n\n/// MerkleTree is work based on Nomad's Merkle.sol, which is used under MIT OR Apache-2.0\n/// [link](https://github.com/nomad-xyz/monorepo/blob/main/packages/contracts-core/contracts/libs/Merkle.sol).\n/// With the following changes:\n/// - Adapted for Solidity 0.8.x.\n/// - Amount of tree leaves stored externally.\n/// - Added thorough documentation.\n/// - `H(0,0) = 0` optimization from [ER forum post](https://ethresear.ch/t/optimizing-sparse-merkle-trees/3751/6).\n/// \u003e Nomad's Merkle.sol is work based on eth2 deposit contract, which is used under CC0-1.0\n///[link](https://github.com/ethereum/deposit_contract/blob/dev/deposit_contract/contracts/validator_registration.v.py).\n/// With the following changes:\n/// \u003e - Implemented in Solidity 0.7.6 (eth2 deposit contract implemented in Vyper).\n/// \u003e - `H() = keccak256()` is used as the hashing function instead of `sha256()`.\nlibrary MerkleTree {\n    /// @dev For root calculation we need at least one empty leaf, thus the minus one in the formula.\n    uint256 internal constant MAX_LEAVES = 2 ** ORIGIN_TREE_HEIGHT - 1;\n\n    // ═════════════════════════════════════════════════ BASE TREE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Inserts `node` into merkle tree\n     * @dev Reverts if tree is full\n     * @param newCount  Amount of inserted leaves in the tree after the insertion (i.e. current + 1)\n     * @param node      Element to insert into tree\n     */\n    function insertBase(BaseTree storage tree, uint256 newCount, bytes32 node) internal {\n        if (newCount \u003e MAX_LEAVES) revert MerkleTreeFull();\n        // We go up the tree following the branch from the empty leaf AFTER the just inserted one.\n        // We stop when we find the first \"right child\" node.\n        // Its sibling is now the rightmost \"left child\" node that has two non-empty children.\n        // Therefore we need to update `tree.branch` value on this level.\n        // One could see that `tree.branch` value on lower and higher levels remain unchanged.\n\n        // Loop invariant: `node` is the current level's value for the branch from JUST INSERTED leaf\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            if ((newCount \u0026 1) == 1) {\n                // Found the first \"right child\" node on the branch from EMPTY leaf\n                // `node` is the value for node on branch from JUST INSERTED leaf\n                // Which in this case is the \"left child\".\n                // We update tree.branch and exit\n                tree.branch[i] = node;\n                return;\n            }\n            // On the branch from EMPTY leaf this is still a \"left child\".\n            // Meaning on branch from JUST INSERTED leaf, `node` is a right child.\n            // We compute value for `node` parent using `tree.branch` invariant:\n            // This is the rightmost \"left child\" node, which would be sibling of `node`.\n            node = MerkleMath.getParent(tree.branch[i], node);\n            // Get the parent index, and go to the next tree level\n            newCount \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n        // As the loop should always end prematurely with the `return` statement,\n        // this code should be unreachable. We assert `false` just to be safe.\n        assert(false);\n    }\n\n    /**\n     * @notice Calculates and returns current root of the merkle tree.\n     * @param count     Current amount of inserted leaves in the tree\n     * @return current  Calculated root of `tree`\n     */\n    function rootBase(BaseTree storage tree, uint256 count) internal view returns (bytes32 current) {\n        // To calculate the root we follow the branch of first EMPTY leaf (index == count)\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            // Check if we are the left or the right child on the current level\n            if ((count \u0026 1) == 1) {\n                // We are the right child. Our sibling is the \"rightmost\" \"left-child\" node\n                // that has two non-empty children → sibling is `tree.branch[i]`\n                current = MerkleMath.getParent(tree.branch[i], current);\n            } else {\n                // We are the left child. Our sibling does not exist yet → sibling is EMPTY\n                current = MerkleMath.getParent(current, bytes32(0));\n            }\n            // Get the parent index, and go to the next tree level\n            count \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    // ══════════════════════════════════════════════ HISTORICAL TREE ══════════════════════════════════════════════════\n\n    /// @notice Initializes the historical roots for the tree by inserting an empty root.\n    // solhint-disable-next-line ordering\n    function initializeRoots(HistoricalTree storage tree) internal returns (bytes32 savedRoot) {\n        // This should only be called once, when the contract is initialized\n        assert(tree.roots.length == 0);\n        // Save root for empty merkle tree: bytes32(0)\n        tree.roots.push(savedRoot);\n    }\n\n    /// @notice Inserts a new leaf into the merkle tree.\n    /// @dev Reverts if tree is full.\n    /// @param node         Element to insert into tree\n    /// @return newRoot     Merkle root after the leaf was inserted\n    function insert(HistoricalTree storage tree, bytes32 node) internal returns (bytes32 newRoot) {\n        // Tree count after the new leaf will be inserted (we store roots[0] as root of empty tree)\n        uint256 newCount = tree.roots.length;\n        tree.tree.insertBase(newCount, node);\n        // Save the new root\n        newRoot = tree.tree.rootBase(newCount);\n        tree.roots.push(newRoot);\n    }\n\n    /// @notice Returns the historical root of the merkle tree.\n    /// @dev Reverts if not enough leafs have been inserted.\n    /// @param count            Amount of leafs in the tree at some point of time\n    /// @return historicalRoot  Merkle root after `count` leafs were inserted\n    function root(HistoricalTree storage tree, uint256 count) internal view returns (bytes32 historicalRoot) {\n        if (count \u003e= tree.roots.length) revert NotEnoughLeafs();\n        return tree.roots[count];\n    }\n\n    // ═══════════════════════════════════════════════ DYNAMIC TREE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Updates the value for the leaf with the given index in the Dynamic Merkle Tree.\n     * @dev Will revert if incorrect proof of inclusion for old value is supplied.\n     * @param tree          Dynamic merkle tree\n     * @param index         Index of the leaf to update\n     * @param oldValue      Previous value of the leaf\n     * @param branch        Proof of inclusion of previous value into the tree\n     * @param newValue      New leaf value to assign\n     * @return newRoot      New value for the Merkle Root after the leaf is updated\n     */\n    function update(\n        DynamicTree storage tree,\n        uint256 index,\n        bytes32 oldValue,\n        bytes32[] memory branch,\n        bytes32 newValue\n    ) internal returns (bytes32 newRoot) {\n        // Check that the old value + proof result in a correct root\n        if (MerkleMath.proofRoot(index, oldValue, branch, AGENT_TREE_HEIGHT) != tree.root) {\n            revert LeafNotProven();\n        }\n        // New root is new value + the same proof (values for sibling nodes are not updated)\n        newRoot = MerkleMath.proofRoot(index, newValue, branch, AGENT_TREE_HEIGHT);\n        // Write the new root\n        tree.root = newRoot;\n    }\n}\n\n// contracts/libs/stack/Tips.sol\n\n/// Tips is encoded data with \"tips paid for sending a base message\".\n/// Note: even though uint256 is also an underlying type for MemView, Tips is stored ON STACK.\ntype Tips is uint256;\n\nusing TipsLib for Tips global;\n\n/// # Tips\n/// Library for formatting _the tips part_ of _the base messages_.\n///\n/// ## How the tips are awarded\n/// Tips are paid for sending a base message, and are split across all the agents that\n/// made the message execution on destination chain possible.\n/// ### Summit tips\n/// Split between:\n///     - Guard posting a snapshot with state ST_G for the origin chain.\n///     - Notary posting a snapshot SN_N using ST_G. This creates attestation A.\n///     - Notary posting a message receipt after it is executed on destination chain.\n/// ### Attestation tips\n/// Paid to:\n///     - Notary posting attestation A to destination chain.\n/// ### Execution tips\n/// Paid to:\n///     - First executor performing a valid execution attempt (correct proofs, optimistic period over),\n///      using attestation A to prove message inclusion on origin chain, whether the recipient reverted or not.\n/// ### Delivery tips.\n/// Paid to:\n///     - Executor who successfully executed the message on destination chain.\n///\n/// ## Tips encoding\n/// - Tips occupy a single storage word, and thus are stored on stack instead of being stored in memory.\n/// - The actual tip values should be determined by multiplying stored values by divided by TIPS_MULTIPLIER=2**32.\n/// - Tips are packed into a single word of storage, while allowing real values up to ~8*10**28 for every tip category.\n/// \u003e The only downside is that the \"real tip values\" are now multiplies of ~4*10**9, which should be fine even for\n/// the chains with the most expensive gas currency.\n/// # Tips stack layout (from highest bits to lowest)\n///\n/// | Position   | Field          | Type   | Bytes | Description                                                |\n/// | ---------- | -------------- | ------ | ----- | ---------------------------------------------------------- |\n/// | (032..024] | summitTip      | uint64 | 8     | Tip for agents interacting with Summit contract            |\n/// | (024..016] | attestationTip | uint64 | 8     | Tip for Notary posting attestation to Destination contract |\n/// | (016..008] | executionTip   | uint64 | 8     | Tip for valid execution attempt on destination chain       |\n/// | (008..000] | deliveryTip    | uint64 | 8     | Tip for successful message delivery on destination chain   |\n\nlibrary TipsLib {\n    using SafeCast for uint256;\n\n    /// @dev Amount of bits to shift to summitTip field\n    uint256 private constant SHIFT_SUMMIT_TIP = 24 * 8;\n    /// @dev Amount of bits to shift to attestationTip field\n    uint256 private constant SHIFT_ATTESTATION_TIP = 16 * 8;\n    /// @dev Amount of bits to shift to executionTip field\n    uint256 private constant SHIFT_EXECUTION_TIP = 8 * 8;\n\n    // ═══════════════════════════════════════════════════ TIPS ════════════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips with the given fields\n    /// @param summitTip_        Tip for agents interacting with Summit contract, divided by TIPS_MULTIPLIER\n    /// @param attestationTip_   Tip for Notary posting attestation to Destination contract, divided by TIPS_MULTIPLIER\n    /// @param executionTip_     Tip for valid execution attempt on destination chain, divided by TIPS_MULTIPLIER\n    /// @param deliveryTip_      Tip for successful message delivery on destination chain, divided by TIPS_MULTIPLIER\n    function encodeTips(uint64 summitTip_, uint64 attestationTip_, uint64 executionTip_, uint64 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // forgefmt: disable-next-item\n        return Tips.wrap(\n            uint256(summitTip_) \u003c\u003c SHIFT_SUMMIT_TIP |\n            uint256(attestationTip_) \u003c\u003c SHIFT_ATTESTATION_TIP |\n            uint256(executionTip_) \u003c\u003c SHIFT_EXECUTION_TIP |\n            uint256(deliveryTip_)\n        );\n    }\n\n    /// @notice Convenience function to encode tips with uint256 values.\n    function encodeTips256(uint256 summitTip_, uint256 attestationTip_, uint256 executionTip_, uint256 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // In practice, the tips amounts are not supposed to be higher than 2**96, and with 32 bits of granularity\n        // using uint64 is enough to store the values. However, we still check for overflow just in case.\n        // TODO: consider using Number type to store the tips values.\n        return encodeTips({\n            summitTip_: (summitTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            attestationTip_: (attestationTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            executionTip_: (executionTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            deliveryTip_: (deliveryTip_ \u003e\u003e TIPS_GRANULARITY).toUint64()\n        });\n    }\n\n    /// @notice Wraps the padded encoded tips into a Tips-typed value.\n    /// @dev There is no actual padding here, as the underlying type is already uint256,\n    /// but we include this function for consistency and to be future-proof, if tips will eventually use anything\n    /// smaller than uint256.\n    function wrapPadded(uint256 paddedTips) internal pure returns (Tips) {\n        return Tips.wrap(paddedTips);\n    }\n\n    /**\n     * @notice Returns a formatted Tips payload specifying empty tips.\n     * @return Formatted tips\n     */\n    function emptyTips() internal pure returns (Tips) {\n        return Tips.wrap(0);\n    }\n\n    /// @notice Returns tips's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Tips tips) internal pure returns (bytes32 hashedTips) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store tips in scratch space\n            mstore(0, tips)\n            // Compute hash of tips padded to 32 bytes\n            hashedTips := keccak256(0, 32)\n        }\n    }\n\n    // ═══════════════════════════════════════════════ TIPS SLICING ════════════════════════════════════════════════════\n\n    /// @notice Returns summitTip field\n    function summitTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_SUMMIT_TIP);\n    }\n\n    /// @notice Returns attestationTip field\n    function attestationTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_ATTESTATION_TIP);\n    }\n\n    /// @notice Returns executionTip field\n    function executionTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_EXECUTION_TIP);\n    }\n\n    /// @notice Returns deliveryTip field\n    function deliveryTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips));\n    }\n\n    // ════════════════════════════════════════════════ TIPS VALUE ═════════════════════════════════════════════════════\n\n    /// @notice Returns total value of the tips payload.\n    /// This is the sum of the encoded values, scaled up by TIPS_MULTIPLIER\n    function value(Tips tips) internal pure returns (uint256 value_) {\n        value_ = uint256(tips.summitTip()) + tips.attestationTip() + tips.executionTip() + tips.deliveryTip();\n        value_ \u003c\u003c= TIPS_GRANULARITY;\n    }\n\n    /// @notice Increases the delivery tip to match the new value.\n    function matchValue(Tips tips, uint256 newValue) internal pure returns (Tips newTips) {\n        uint256 oldValue = tips.value();\n        if (newValue \u003c oldValue) revert TipsValueTooLow();\n        // We want to increase the delivery tip, while keeping the other tips the same\n        unchecked {\n            uint256 delta = (newValue - oldValue) \u003e\u003e TIPS_GRANULARITY;\n            // `delta` fits into uint224, as TIPS_GRANULARITY is 32, so this never overflows uint256.\n            // In practice, this will never overflow uint64 as well, but we still check it just in case.\n            if (delta + tips.deliveryTip() \u003e type(uint64).max) revert TipsOverflow();\n            // Delivery tips occupy lowest 8 bytes, so we can just add delta to the tips value\n            // to effectively increase the delivery tip (knowing that delta fits into uint64).\n            newTips = Tips.wrap(Tips.unwrap(tips) + delta);\n        }\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    function __Ownable_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable_init_unchained() internal onlyInitializing {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n    function __Ownable2Step_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable2Step_init_unchained() internal onlyInitializing {\n    }\n    address private _pendingOwner;\n\n    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Returns the address of the pending owner.\n     */\n    function pendingOwner() public view virtual returns (address) {\n        return _pendingOwner;\n    }\n\n    /**\n     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual override onlyOwner {\n        _pendingOwner = newOwner;\n        emit OwnershipTransferStarted(owner(), newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual override {\n        delete _pendingOwner;\n        super._transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev The new owner accepts the ownership transfer.\n     */\n    function acceptOwnership() public virtual {\n        address sender = _msgSender();\n        require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n        _transferOwnership(sender);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// contracts/libs/memory/State.sol\n\n/// State is a memory view over a formatted state payload.\ntype State is uint256;\n\nusing StateLib for State global;\n\n/// # State\n/// State structure represents the state of Origin contract at some point of time.\n/// - State is structured in a way to track the updates of the Origin Merkle Tree.\n/// - State includes root of the Origin Merkle Tree, origin domain and some additional metadata.\n/// ## Origin Merkle Tree\n/// Hash of every sent message is inserted in the Origin Merkle Tree, which changes\n/// the value of Origin Merkle Root (which is the root for the mentioned tree).\n/// - Origin has a single Merkle Tree for all messages, regardless of their destination domain.\n/// - This leads to Origin state being updated if and only if a message was sent in a block.\n/// - Origin contract is a \"source of truth\" for states: a state is considered \"valid\" in its Origin,\n/// if it matches the state of the Origin contract after the N-th (nonce) message was sent.\n///\n/// # Memory layout of State fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                    |\n/// | ---------- | ----------- | ------- | ----- | ------------------------------ |\n/// | [000..032) | root        | bytes32 | 32    | Root of the Origin Merkle Tree |\n/// | [032..036) | origin      | uint32  | 4     | Domain where Origin is located |\n/// | [036..040) | nonce       | uint32  | 4     | Amount of sent messages        |\n/// | [040..045) | blockNumber | uint40  | 5     | Block of last sent message     |\n/// | [045..050) | timestamp   | uint40  | 5     | Time of last sent message      |\n/// | [050..062) | gasData     | uint96  | 12    | Gas data for the chain         |\n///\n/// @dev State could be used to form a Snapshot to be signed by a Guard or a Notary.\nlibrary StateLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_ROOT = 0;\n    uint256 private constant OFFSET_ORIGIN = 32;\n    uint256 private constant OFFSET_NONCE = 36;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 40;\n    uint256 private constant OFFSET_TIMESTAMP = 45;\n    uint256 private constant OFFSET_GAS_DATA = 50;\n\n    // ═══════════════════════════════════════════════════ STATE ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted State payload with provided fields\n     * @param root_         New merkle root\n     * @param origin_       Domain of Origin's chain\n     * @param nonce_        Nonce of the merkle root\n     * @param blockNumber_  Block number when root was saved in Origin\n     * @param timestamp_    Block timestamp when root was saved in Origin\n     * @param gasData_      Gas data for the chain\n     * @return Formatted state\n     */\n    function formatState(\n        bytes32 root_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_,\n        GasData gasData_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(root_, origin_, nonce_, blockNumber_, timestamp_, gasData_);\n    }\n\n    /**\n     * @notice Returns a State view over the given payload.\n     * @dev Will revert if the payload is not a state.\n     */\n    function castToState(bytes memory payload) internal pure returns (State) {\n        return castToState(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a State view.\n     * @dev Will revert if the memory view is not over a state.\n     */\n    function castToState(MemView memView) internal pure returns (State) {\n        if (!isState(memView)) revert UnformattedState();\n        return State.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted State.\n    function isState(MemView memView) internal pure returns (bool) {\n        return memView.len() == STATE_LENGTH;\n    }\n\n    /// @notice Returns the hash of a State, that could be later signed by a Guard to signal\n    /// that the state is invalid.\n    function hashInvalid(State state) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(stateInvalidSalt, keccak(state))\n        return state.unwrap().keccakSalted(STATE_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(State state) internal pure returns (MemView) {\n        return MemView.wrap(State.unwrap(state));\n    }\n\n    /// @notice Compares two State structures.\n    function equals(State a, State b) internal pure returns (bool) {\n        // Length of a State payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═══════════════════════════════════════════════ STATE HASHING ═══════════════════════════════════════════════════\n\n    /// @notice Returns the hash of the State.\n    /// @dev We are using the Merkle Root of a tree with two leafs (see below) as state hash.\n    function leaf(State state) internal pure returns (bytes32) {\n        (bytes32 leftLeaf_, bytes32 rightLeaf_) = state.subLeafs();\n        // Final hash is the parent of these leafs\n        return keccak256(bytes.concat(leftLeaf_, rightLeaf_));\n    }\n\n    /// @notice Returns \"sub-leafs\" of the State. Hash of these \"sub leafs\" is going to be used\n    /// as a \"state leaf\" in the \"Snapshot Merkle Tree\".\n    /// This enables proving that leftLeaf = (root, origin) was a part of the \"Snapshot Merkle Tree\",\n    /// by combining `rightLeaf` with the remainder of the \"Snapshot Merkle Proof\".\n    function subLeafs(State state) internal pure returns (bytes32 leftLeaf_, bytes32 rightLeaf_) {\n        MemView memView = state.unwrap();\n        // Left leaf is (root, origin)\n        leftLeaf_ = memView.prefix({len_: OFFSET_NONCE}).keccak();\n        // Right leaf is (metadata), or (nonce, blockNumber, timestamp)\n        rightLeaf_ = memView.sliceFrom({index_: OFFSET_NONCE}).keccak();\n    }\n\n    /// @notice Returns the left \"sub-leaf\" of the State.\n    function leftLeaf(bytes32 root_, uint32 origin_) internal pure returns (bytes32) {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(root_, origin_));\n    }\n\n    /// @notice Returns the right \"sub-leaf\" of the State.\n    function rightLeaf(uint32 nonce_, uint40 blockNumber_, uint40 timestamp_, GasData gasData_)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(nonce_, blockNumber_, timestamp_, gasData_));\n    }\n\n    // ═══════════════════════════════════════════════ STATE SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns a historical Merkle root from the Origin contract.\n    function root(State state) internal pure returns (bytes32) {\n        return state.unwrap().index({index_: OFFSET_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns domain of chain where the Origin contract is deployed.\n    function origin(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns nonce of Origin contract at the time, when `root` was the Merkle root.\n    function nonce(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when `root` was saved in Origin.\n    function blockNumber(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when `root` was saved in Origin.\n    /// @dev This is the timestamp according to the origin chain.\n    function timestamp(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n\n    /// @notice Returns gas data for the chain.\n    function gasData(State state) internal pure returns (GasData) {\n        return GasDataLib.wrapGasData(state.unwrap().indexUint({index_: OFFSET_GAS_DATA, bytes_: GAS_DATA_LENGTH}));\n    }\n}\n\n// contracts/libs/memory/BaseMessage.sol\n\n/// BaseMessage is a memory view over the base message supported by Origin-Destination\ntype BaseMessage is uint256;\n\nusing BaseMessageLib for BaseMessage global;\n\n/// BaseMessage structure represents a base message sent via the Origin-Destination contracts.\n/// - It only contains data relevant to the base message, the rest of data is encoded in the message header.\n/// - `sender` and `recipient` for EVM chains are EVM addresses casted to bytes32, while preserving left-alignment.\n/// - `tips` and `request` parameters are specified by a message sender\n/// \u003e Origin will calculate minimum tips for given request and content length, and will reject messages with tips\n/// lower than that.\n///\n/// # Memory layout of BaseMessage fields\n///\n/// | Position   | Field     | Type    | Bytes | Description                            |\n/// | ---------- | --------- | ------- | ----- | -------------------------------------- |\n/// | [000..032) | tips      | uint256 | 32    | Encoded tips paid on origin chain      |\n/// | [032..064) | sender    | bytes32 | 32    | Sender address on origin chain         |\n/// | [064..096) | recipient | bytes32 | 32    | Recipient address on destination chain |\n/// | [096..116) | request   | uint160 | 20    | Encoded request for message execution  |\n/// | [104..AAA) | content   | bytes   | ??    | Content to be passed to recipient      |\nlibrary BaseMessageLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_TIPS = 0;\n    uint256 private constant OFFSET_SENDER = 32;\n    uint256 private constant OFFSET_RECIPIENT = 64;\n    uint256 private constant OFFSET_REQUEST = OFFSET_RECIPIENT + TIPS_LENGTH;\n    uint256 private constant OFFSET_CONTENT = OFFSET_REQUEST + REQUEST_LENGTH;\n\n    // ═══════════════════════════════════════════════ BASE MESSAGE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted BaseMessage payload with provided fields.\n     * @param tips_         Encoded tips information\n     * @param sender_       Sender address on origin chain\n     * @param recipient_    Recipient address on destination chain\n     * @param request_      Encoded request for message execution\n     * @param content_      Raw content to be passed to recipient on destination chain\n     * @return Formatted base message\n     */\n    function formatBaseMessage(Tips tips_, bytes32 sender_, bytes32 recipient_, Request request_, bytes memory content_)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return abi.encodePacked(tips_, sender_, recipient_, request_, content_);\n    }\n\n    /**\n     * @notice Returns a BaseMessage view over the given payload.\n     * @dev Will revert if the payload is not a base message.\n     */\n    function castToBaseMessage(bytes memory payload) internal pure returns (BaseMessage) {\n        return castToBaseMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a BaseMessage view.\n     * @dev Will revert if the memory view is not over a base message payload.\n     */\n    function castToBaseMessage(MemView memView) internal pure returns (BaseMessage) {\n        if (!isBaseMessage(memView)) revert UnformattedBaseMessage();\n        return BaseMessage.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted BaseMessage.\n    function isBaseMessage(MemView memView) internal pure returns (bool) {\n        // Check if sender, recipient, tips fields exist\n        return (memView.len() \u003e= OFFSET_CONTENT);\n        // Content could be empty, so we don't check that\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(BaseMessage baseMessage) internal pure returns (MemView) {\n        return MemView.wrap(BaseMessage.unwrap(baseMessage));\n    }\n\n    /// @notice Returns baseMessage's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        // We hash \"tips\" and \"everything but tips\" to make tips proofs easier to verify\n        return MerkleMath.getParent(baseMessage.tips().leaf(), baseMessage.bodyLeaf());\n    }\n\n    /// @notice Returns hash for the \"everything but tips\" part of the base message.\n    function bodyLeaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_SENDER}).keccak();\n    }\n\n    // ═══════════════════════════════════════════ BASE MESSAGE SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips paid on origin chain.\n    function tips(BaseMessage baseMessage) internal pure returns (Tips) {\n        return TipsLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_TIPS, bytes_: TIPS_LENGTH})));\n    }\n\n    /// @notice Returns sender address on origin chain.\n    function sender(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_SENDER, bytes_: 32});\n    }\n\n    /// @notice Returns recipient address on destination chain.\n    function recipient(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_RECIPIENT, bytes_: 32});\n    }\n\n    /// @notice Returns an encoded request for message execution on destination chain.\n    function request(BaseMessage baseMessage) internal pure returns (Request) {\n        return RequestLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_REQUEST, bytes_: REQUEST_LENGTH})));\n    }\n\n    /// @notice Returns an untyped memory view over the content to be passed to recipient.\n    function content(BaseMessage baseMessage) internal pure returns (MemView) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_CONTENT});\n    }\n}\n\n// contracts/base/MessagingBase.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for all messaging contracts.\n * - Provides context on the local chain's domain.\n * - Provides ownership functionality.\n * - Will be providing pausing functionality when it is implemented.\n */\nabstract contract MessagingBase is MultiCallable, Versioned, Ownable2StepUpgradeable {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @notice Domain of the local chain, set once upon contract creation\n    uint32 public immutable localDomain;\n    // @notice Domain of the Synapse chain, set once upon contract creation\n    uint32 public immutable synapseDomain;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev gap for upgrade safety\n    uint256[50] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    constructor(string memory version_, uint32 synapseDomain_) Versioned(version_) {\n        localDomain = ChainContext.chainId();\n        synapseDomain = synapseDomain_;\n    }\n\n    // TODO: Implement pausing\n\n    /**\n     * @dev Should be impossible to renounce ownership;\n     * we override OpenZeppelin OwnableUpgradeable's\n     * implementation of renounceOwnership to make it a no-op\n     */\n    function renounceOwnership() public override onlyOwner {} //solhint-disable-line no-empty-blocks\n}\n\n// contracts/libs/memory/Message.sol\n\n/// Message is a memory over over a formatted message payload.\ntype Message is uint256;\n\nusing MessageLib for Message global;\n\n/// Library for formatting the various messages supported by Origin and Destination.\n///\n/// # Message memory layout\n///\n/// | Position   | Field  | Type    | Bytes | Description                                             |\n/// | ---------- | ------ | ------- | ----- | ------------------------------------------------------- |\n/// | [000..017) | header | uint136 | 17    | Encoded general routing information for the message     |\n/// | [017..AAA) | body   | bytes   | ??    | Formatted payload (according to flag) with message body |\nlibrary MessageLib {\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MemViewLib for bytes;\n    using HeaderLib for MemView;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_HEADER = 0;\n    uint256 private constant OFFSET_BODY = OFFSET_HEADER + HEADER_LENGTH;\n\n    // ══════════════════════════════════════════════════ MESSAGE ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns formatted message with provided fields.\n     * @param header_   Encoded general routing information for the message\n     * @param body_     Formatted payload (according to flag) with message body\n     * @return Formatted message\n     */\n    function formatMessage(Header header_, bytes memory body_) internal pure returns (bytes memory) {\n        return abi.encodePacked(header_, body_);\n    }\n\n    /**\n     * @notice Returns a Message view over for the given payload.\n     * @dev Will revert if the payload is not a message payload.\n     */\n    function castToMessage(bytes memory payload) internal pure returns (Message) {\n        return castToMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Message view.\n     * @dev Will revert if the memory view is not over a message payload.\n     */\n    function castToMessage(MemView memView) internal pure returns (Message) {\n        if (!isMessage(memView)) revert UnformattedMessage();\n        return Message.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Message.\n     */\n    function isMessage(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Check if headers exist in the payload\n        if (length \u003c OFFSET_BODY) return false;\n        // Check that Header is valid\n        uint256 paddedHeader = _header(memView);\n        if (!HeaderLib.isHeader(paddedHeader)) return false;\n        // Check that body is formatted according to the flag\n        // Only Base/Manager message flags exist\n        if (HeaderLib.wrapPadded(paddedHeader).flag() == MessageFlag.Base) {\n            // Check if body is a formatted base message\n            return _body(memView).isBaseMessage();\n        } else {\n            // Check if body is a formatted calldata for AgentManager call\n            return _body(memView).isCallData();\n        }\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Message message) internal pure returns (MemView) {\n        return MemView.wrap(Message.unwrap(message));\n    }\n\n    /// @notice Returns message's hash: a leaf to be inserted in the Merkle tree.\n    function leaf(Message message) internal pure returns (bytes32) {\n        // We hash header and body separately to make message proofs easier to verify\n        Header header_ = message.header();\n        // Only Base/Manager message flags exist\n        if (header_.flag() == MessageFlag.Base) {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToBaseMessage().leaf());\n        } else {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToCallData().leaf());\n        }\n    }\n\n    // ══════════════════════════════════════════════ MESSAGE SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns message's encoded header field.\n    function header(Message message) internal pure returns (Header) {\n        return HeaderLib.wrapPadded((message.unwrap().indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH})));\n    }\n\n    /// @notice Returns message's body field as an untyped memory view.\n    function body(Message message) internal pure returns (MemView) {\n        MemView memView = message.unwrap();\n        return _body(memView);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns message's padded header without checking that it is a valid header.\n    function _header(MemView memView) private pure returns (uint256) {\n        return memView.indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH});\n    }\n\n    /// @dev Returns an untyped memory view over the body field without checking\n    /// if the whole payload or the body are properly formatted.\n    function _body(MemView memView) private pure returns (MemView) {\n        return memView.sliceFrom({index_: OFFSET_BODY});\n    }\n}\n\n// contracts/base/AgentSecured.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for messaging contracts that are secured by the agent manager.\n * `AgentSecured` relies on `AgentManager` to provide the following functionality:\n * - Keep track of agents and their statuses.\n * - Pass agent-signed statements that were verified by the agent manager.\n * - These statements are considered valid indefinitely, unless the agent is disputed.\n * - Disputes are opened and resolved by the agent manager.\n * \u003e `AgentSecured` implementation should never use statements signed by agents that are disputed.\n */\nabstract contract AgentSecured is MessagingBase, IAgentSecured {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    address public immutable agentManager;\n\n    /// @inheritdoc IAgentSecured\n    address public immutable inbox;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    // (agent index =\u003e their dispute status: flag, openedAt, resolvedAt)\n    mapping(uint32 =\u003e DisputeStatus) internal _disputes;\n\n    /// @dev gap for upgrade safety\n    uint256[49] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    modifier onlyAgentManager() {\n        if (msg.sender != agentManager) revert CallerNotAgentManager();\n        _;\n    }\n\n    modifier onlyInbox() {\n        if (msg.sender != inbox) revert CallerNotInbox();\n        _;\n    }\n\n    constructor(string memory version_, uint32 synapseDomain_, address agentManager_, address inbox_)\n        MessagingBase(version_, synapseDomain_)\n    {\n        agentManager = agentManager_;\n        inbox = inbox_;\n    }\n\n    // ════════════════════════════════════════════ ONLY AGENT MANAGER ═════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external onlyAgentManager {\n        uint40 openedAt = ChainContext.blockTimestamp();\n        DisputeStatus memory status = DisputeStatus({flag: DisputeFlag.Pending, openedAt: openedAt, resolvedAt: 0});\n        _disputes[guardIndex] = status;\n        _disputes[notaryIndex] = status;\n    }\n\n    /// @inheritdoc IAgentSecured\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external onlyAgentManager {\n        // Update the dispute status of the slashed agent first.\n        uint40 resolvedAt = ChainContext.blockTimestamp();\n        _disputes[slashedIndex].flag = DisputeFlag.Slashed;\n        _disputes[slashedIndex].resolvedAt = resolvedAt;\n        // Mark the rival agent as not disputed, if there was an ongoing dispute.\n        if (rivalIndex != 0) {\n            _disputes[rivalIndex].flag = DisputeFlag.None;\n            _disputes[rivalIndex].resolvedAt = resolvedAt;\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function agentStatus(address agent) external view returns (AgentStatus memory) {\n        return _agentStatus(agent);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status) {\n        return _getAgent(index);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory) {\n        return _disputes[agentIndex];\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns status of the given agent: (flag, domain, index).\n    function _agentStatus(address agent) internal view returns (AgentStatus memory) {\n        return IAgentManager(agentManager).agentStatus(agent);\n    }\n\n    /// @dev Returns agent and their status for a given agent index. Returns zero values for non existing indexes.\n    function _getAgent(uint256 index) internal view returns (address agent, AgentStatus memory status) {\n        return IAgentManager(agentManager).getAgent(index);\n    }\n\n    /// @dev Checks if a Dispute exists for the given Notary. This function returns true, if\n    /// Notary is in ongoing Dispute, or if Dispute was resolved not in Notary's favor.\n    /// In both cases we can't trust Notary's data.\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeExists(uint32 notaryIndex) internal view returns (bool) {\n        return _disputes[notaryIndex].flag != DisputeFlag.None;\n    }\n\n    /// @dev Checks if a Notary recently won a Dispute and is still in the \"post-dispute\" timeout period.\n    /// In this period we still can't trust Notary's data, though we can optimistically assume that\n    /// that the data will be correct after the timeout (assuming no new Disputes are opened).\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeTimeout(uint32 notaryIndex) internal view returns (bool) {\n        DisputeStatus memory status = _disputes[notaryIndex];\n        // Exit early if Notary is in ongoing Dispute / slashed.\n        if (status.flag != DisputeFlag.None) return false;\n        // Check if Notary has been in any Dispute at all.\n        if (status.openedAt == 0) return false;\n        // Otherwise check if the Dispute timeout is still active.\n        return block.timestamp \u003c status.resolvedAt + DISPUTE_TIMEOUT_NOTARY;\n    }\n}\n\n// contracts/hubs/StateHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StateHub` is a parent contract for `Origin`. It is responsible for the following:\n/// - Keeping track of the historical Origin Merkle Tree containing all the message hashes.\n/// - Keeping track of the historical Origin States, as well as verifying their validity.\nabstract contract StateHub is AgentSecured, StateHubEvents, IStateHub {\n    using SafeCast for uint256;\n    using StateLib for bytes;\n\n    struct OriginState {\n        uint40 blockNumber;\n        uint40 timestamp;\n        GasData gasData;\n    }\n    // Bits left for tight packing: 80\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Historical Merkle Tree\n    /// Note: Takes two storage slots\n    HistoricalTree private _tree;\n\n    /// @dev All historical contract States\n    OriginState[] private _originStates;\n\n    /// @dev gap for upgrade safety\n    uint256[47] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IStateHub\n    function isValidState(bytes memory statePayload) external view returns (bool isValid) {\n        // This will revert if payload is not a formatted state\n        State state = statePayload.castToState();\n        return _isValidState(state);\n    }\n\n    /// @inheritdoc IStateHub\n    function statesAmount() external view returns (uint256) {\n        return _originStates.length;\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestLatestState() external view returns (bytes memory stateData) {\n        // This never underflows, assuming the contract was initialized\n        return suggestState(_nextNonce() - 1);\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestState(uint32 nonce) public view returns (bytes memory stateData) {\n        // This will revert if nonce is out of range\n        bytes32 root = _tree.root(nonce);\n        return _formatOriginState(_originStates[nonce], root, localDomain, nonce);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Initializes the saved states list by inserting a state for an empty Merkle Tree.\n    function _initializeStates() internal {\n        // This should only be called once, when the contract is initialized\n        // This will revert if _tree.roots is non-empty\n        bytes32 savedRoot = _tree.initializeRoots();\n        // Save root for empty merkle _tree with block number and timestamp of initialization\n        _saveState(savedRoot, _toOriginState());\n    }\n\n    /// @dev Inserts leaf into the Merkle Tree and saves the updated origin State.\n    function _insertAndSave(bytes32 leaf) internal {\n        bytes32 newRoot = _tree.insert(leaf);\n        _saveState(newRoot, _toOriginState());\n    }\n\n    /// @dev Saves an updated state of the Origin contract\n    function _saveState(bytes32 root, OriginState memory state) internal {\n        uint32 nonce = _nextNonce();\n        _originStates.push(state);\n        // Emit event with raw state data\n        emit StateSaved(_formatOriginState(state, root, localDomain, nonce));\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns nonce of the next sent message: the amount of saved States so far.\n    /// This always equals to \"total amount of sent messages\" plus 1.\n    function _nextNonce() internal view returns (uint32) {\n        // TODO: consider using more than 32 bits for origin nonces\n        return _originStates.length.toUint32();\n    }\n\n    /// @dev Checks if a state is valid, i.e. if it matches the historical one.\n    /// Reverts, if state refers to another Origin contract.\n    function _isValidState(State state) internal view returns (bool) {\n        // Check if state refers to this contract\n        if (state.origin() != localDomain) revert IncorrectOriginDomain();\n        // Check if nonce exists\n        uint32 nonce = state.nonce();\n        if (nonce \u003e= _originStates.length) return false;\n        // Check if state root matches the historical one\n        if (state.root() != _tree.root(nonce)) return false;\n        // Check if state metadata matches the historical one\n        return _areEqual(state, _originStates[nonce]);\n    }\n\n    // ═════════════════════════════════════════════ STRUCT FORMATTING ═════════════════════════════════════════════════\n\n    /// @dev Returns a formatted payload for a stored OriginState.\n    function _formatOriginState(OriginState memory originState, bytes32 root, uint32 origin, uint32 nonce)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return StateLib.formatState({\n            root_: root,\n            origin_: origin,\n            nonce_: nonce,\n            blockNumber_: originState.blockNumber,\n            timestamp_: originState.timestamp,\n            gasData_: originState.gasData\n        });\n    }\n\n    /// @dev Child contract should implement the logic for getting the current gas data from the gas oracle\n    /// to be saved as part of the Origin State.\n    // solhint-disable-next-line ordering\n    function _fetchGasData() internal view virtual returns (GasData);\n\n    /// @dev Returns a OriginState struct to save in the contract.\n    function _toOriginState() internal view returns (OriginState memory originState) {\n        originState.blockNumber = ChainContext.blockNumber();\n        originState.timestamp = ChainContext.blockTimestamp();\n        originState.gasData = _fetchGasData();\n    }\n\n    /// @dev Checks that a state and its Origin representation are equal.\n    function _areEqual(State state, OriginState memory originState) internal pure returns (bool) {\n        return state.blockNumber() == originState.blockNumber \u0026\u0026 state.timestamp() == originState.timestamp;\n    }\n}\n\n// contracts/Origin.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Origin` contract is used for sending messages to remote chains. It is done\n/// by inserting the message hashes into the Origin Merkle, which makes it possible to\n/// prove that message was sent using the Merkle proof against the Origin Merkle Root. This essentially\n/// compresses the list of messages into a single 32-byte value that needs to be stored on the destination chain.\n/// `Origin` is responsible for the following:\n/// - Formatting the sent message payloads, and inserting their hashes into the Origin Merkle Tree.\n/// - Keeping track of its own historical states (see parent contract `StateHub`).\n/// - Enforcing minimum tip values for sent base messages based on the provided execution requests.\n/// - Distributing the collected tips upon request from a local `AgentManager` contract.\ncontract Origin is StateHub, OriginEvents, InterfaceOrigin {\n    using MemViewLib for bytes;\n    using MessageLib for bytes;\n    using TipsLib for bytes;\n    using TypeCasts for address;\n\n    address public immutable gasOracle;\n\n    modifier onlyRemoteDestination(uint32 destination) {\n        if (destination == localDomain) revert IncorrectDestinationDomain();\n        _;\n    }\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_, address gasOracle_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {\n        gasOracle = gasOracle_;\n    }\n\n    /// @notice Initializes Origin contract:\n    /// - msg.sender is set as contract owner\n    /// - State of \"empty merkle tree\" is saved\n    function initialize() external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize \"states\": state of an \"empty merkle tree\" is saved\n        _initializeStates();\n    }\n\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable onlyRemoteDestination(destination) returns (uint32 messageNonce, bytes32 messageHash) {\n        // Check that content is not too large\n        if (content.length \u003e MAX_CONTENT_BYTES) revert ContentLengthTooBig();\n        // This will revert if msg.value is lower than value of minimum tips\n        Tips tips = _getMinimumTips(destination, paddedRequest, content.length).matchValue(msg.value);\n        Request request = RequestLib.wrapPadded(paddedRequest);\n        // Format the BaseMessage body\n        bytes memory body = BaseMessageLib.formatBaseMessage({\n            sender_: msg.sender.addressToBytes32(),\n            recipient_: recipient,\n            tips_: tips,\n            request_: request,\n            content_: content\n        });\n        // Send the message\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Base, body);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        onlyAgentManager\n        onlyRemoteDestination(destination)\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // AgentManager (checked via modifier) is responsible for constructing the calldata payload correctly.\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Manager, payload);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function withdrawTips(address recipient, uint256 amount) external onlyAgentManager {\n        if (address(this).balance \u003c amount) revert InsufficientEthBalance();\n        (bool success,) = recipient.call{value: amount}(\"\");\n        if (!success) revert EthTransferFailed();\n        emit TipWithdrawalCompleted(recipient, amount);\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue)\n    {\n        return _getMinimumTips(destination, paddedRequest, contentLength).value();\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Sends the given message to the specified destination. Message hash is inserted\n    /// into the Origin Merkle Tree, which will enable message execution on destination chain.\n    function _sendMessage(uint32 destination, uint32 optimisticPeriod, MessageFlag flag, bytes memory body)\n        internal\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // Format the message header\n        messageNonce = _nextNonce();\n        Header header = flag.encodeHeader({\n            origin_: localDomain,\n            nonce_: messageNonce,\n            destination_: destination,\n            optimisticPeriod_: optimisticPeriod\n        });\n        // Format the full message payload\n        bytes memory msgPayload = MessageLib.formatMessage(header, body);\n        // Insert new leaf into the Origin Merkle Tree and save the updated state\n        messageHash = msgPayload.castToMessage().leaf();\n        _insertAndSave(messageHash);\n        // Emit event with message information\n        emit Sent(messageHash, messageNonce, destination, msgPayload);\n        // Update the gas oracle data. We do this after the provided tips are checked so that\n        // the provided message is sent in the event that the gas oracle data is updated to a higher value.\n        InterfaceGasOracle(gasOracle).updateGasData(destination);\n        // TODO: consider doing this before the message is sent, while adjusting GasOracle.getMinimumTips() to\n        // use the pending gas oracle data.\n    }\n\n    /// @dev Returns the minimum tips for sending a message to the given destination with the given request and content.\n    function _getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        internal\n        view\n        returns (Tips)\n    {\n        return\n            TipsLib.wrapPadded(InterfaceGasOracle(gasOracle).getMinimumTips(destination, paddedRequest, contentLength));\n    }\n\n    /// @dev Gets the current gas data from the gas oracle to be saved as part of the Origin State.\n    function _fetchGasData() internal view override returns (GasData) {\n        return GasDataLib.wrapGasData(InterfaceGasOracle(gasOracle).getGasData());\n    }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"190716:4880:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;190716:4880:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"190716:4880:0:-:0;;;;;;;;","abiDefinition":[],"userDoc":{"kind":"user","methods":{},"notice":"BaseMessage structure represents a base message sent via the Origin-Destination contracts. - It only contains data relevant to the base message, the rest of data is encoded in the message header. - `sender` and `recipient` for EVM chains are EVM addresses casted to bytes32, while preserving left-alignment. - `tips` and `request` parameters are specified by a message sender \u003e Origin will calculate minimum tips for given request and content length, and will reject messages with tips lower than that. # Memory layout of BaseMessage fields | Position   | Field     | Type    | Bytes | Description                            | | ---------- | --------- | ------- | ----- | -------------------------------------- | | [000..032) | tips      | uint256 | 32    | Encoded tips paid on origin chain      | | [032..064) | sender    | bytes32 | 32    | Sender address on origin chain         | | [064..096) | recipient | bytes32 | 32    | Recipient address on destination chain | | [096..116) | request   | uint160 | 20    | Encoded request for message execution  | | [104..AAA) | content   | bytes   | ??    | Content to be passed to recipient      |","version":1},"developerDoc":{"kind":"dev","methods":{},"stateVariables":{"OFFSET_TIPS":{"details":"The variables below are not supposed to be used outside of the library directly."}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"stateVariables\":{\"OFFSET_TIPS\":{\"details\":\"The variables below are not supposed to be used outside of the library directly.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"BaseMessage structure represents a base message sent via the Origin-Destination contracts. - It only contains data relevant to the base message, the rest of data is encoded in the message header. - `sender` and `recipient` for EVM chains are EVM addresses casted to bytes32, while preserving left-alignment. - `tips` and `request` parameters are specified by a message sender \u003e Origin will calculate minimum tips for given request and content length, and will reject messages with tips lower than that. # Memory layout of BaseMessage fields | Position   | Field     | Type    | Bytes | Description                            | | ---------- | --------- | ------- | ----- | -------------------------------------- | | [000..032) | tips      | uint256 | 32    | Encoded tips paid on origin chain      | | [032..064) | sender    | bytes32 | 32    | Sender address on origin chain         | | [064..096) | recipient | bytes32 | 32    | Recipient address on destination chain | | [096..116) | request   | uint160 | 20    | Encoded request for message execution  | | [104..AAA) | content   | bytes   | ??    | Content to be passed to recipient      |\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Origin.sol\":\"BaseMessageLib\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Origin.sol\":{\"keccak256\":\"0x96775924f147f3d1f8df8cdf56731fe52a15af8d8e12e608efb8158c112b18cd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e642a27f5fab3c62b4c02e9754e9e42b1cf2e5381dbea9d3d106d23b7772ebe6\",\"dweb:/ipfs/QmUwn7ZyBvPkjnMuK8ZMSexBUdNQnVtxwyoAyT4DXLQjra\"]}},\"version\":1}"},"hashes":{}},"solidity/Origin.sol:ByteString":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220dbc99f26a71024b6fb343e14990dddff1461584aa9e237798d5856c2e682f4e764736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220dbc99f26a71024b6fb343e14990dddff1461584aa9e237798d5856c2e682f4e764736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/OriginEvents.sol\n\n/// @notice A collection of events emitted by the Origin contract\nabstract contract OriginEvents {\n    /**\n     * @notice Emitted when a new message is sent.\n     * @param messageHash   Hash of message; the leaf inserted to the Merkle tree for the message\n     * @param nonce         Nonce of sent message (starts from 1)\n     * @param destination   Destination domain\n     * @param message       Raw bytes of message\n     */\n    event Sent(bytes32 indexed messageHash, uint32 indexed nonce, uint32 indexed destination, bytes message);\n\n    /**\n     * @notice Emitted when a tip withdrawal is completed.\n     * @param actor     Actor address\n     * @param tip       Tip value, denominated in local domain's wei\n     */\n    event TipWithdrawalCompleted(address actor, uint256 tip);\n}\n\n// contracts/events/StateHubEvents.sol\n\n/// @notice A collection of events emitted by the StateHub contract\nabstract contract StateHubEvents {\n    /**\n     * @notice Emitted when a new Origin State is saved after a message was sent.\n     * @param state     Raw payload with state data\n     */\n    event StateSaved(bytes state);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n    /**\n     * @notice Check that a given state is valid: matches the historical state of Origin contract.\n     * Note: any Agent including an invalid state in their snapshot will be slashed\n     * upon providing the snapshot and agent signature for it to Origin contract.\n     * @dev Will revert if any of these is true:\n     *  - State payload is not properly formatted.\n     * @param statePayload      Raw payload with state data\n     * @return isValid          Whether the provided state is valid\n     */\n    function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns the amount of saved states so far.\n     * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n     */\n    function statesAmount() external view returns (uint256);\n\n    /**\n     * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @return statePayload     Raw payload with the latest state data\n     */\n    function suggestLatestState() external view returns (bytes memory statePayload);\n\n    /**\n     * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @param nonce             Historical nonce to form a state\n     * @return statePayload     Raw payload with historical state data\n     */\n    function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/InterfaceGasOracle.sol\n\ninterface InterfaceGasOracle {\n    /**\n     * @notice Fetches the latest gas data for the chain from `Destination` contract,\n     * and uses it to update the oracle values for the requested chain.\n     * @param domain    Domain to update the gas data for\n     */\n    function updateGasData(uint32 domain) external;\n\n    /**\n     * @notice Returns the gas data for the local chain.\n     */\n    function getGasData() external view returns (uint256 paddedGasData);\n\n    /**\n     * @notice Returns the gas data for the given domain, in the decoded format.\n     * @param domain        Domain of chain to get gas data for\n     * @return gasPrice     Gas price for the chain (in Wei per gas unit)\n     * @return dataPrice    Calldata price (in Wei per byte of content)\n     * @return execBuffer   Tx fee safety buffer for message execution (in Wei)\n     * @return amortAttCost Amortized cost for attestation submission (in Wei)\n     * @return etherPrice   Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n     * @return markup       Markup for the message execution (in BWAD)\n     */\n    function getDecodedGasData(uint32 domain)\n        external\n        view\n        returns (\n            uint256 gasPrice,\n            uint256 dataPrice,\n            uint256 execBuffer,\n            uint256 amortAttCost,\n            uint256 etherPrice,\n            uint256 markup\n        );\n\n    /**\n     * @notice Returns the minimum tips for sending a message to a given destination.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return paddedTips       Padded encoded minimum tips information\n     */\n    function getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 paddedTips);\n}\n\n// contracts/interfaces/InterfaceOrigin.sol\n\ninterface InterfaceOrigin {\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /**\n     * @notice Send a message to the recipient located on destination domain.\n     * @dev Recipient has to conform to IMessageRecipient interface, otherwise message won't be delivered.\n     * Will revert if any of these is true:\n     * - `destination` is equal to contract's local domain\n     * - `content` length is greater than `MAX_CONTENT_BYTES`\n     * - `msg.value` is lower than value of minimum tips for the given message\n     * @param destination           Domain of destination chain\n     * @param recipient             Address of recipient on destination chain as bytes32\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param paddedRequest         Padded encoded message execution request on destination chain\n     * @param content               Raw bytes content of message\n     * @return messageNonce         Nonce of the sent message\n     * @return messageHash          Hash of the sent message\n     */\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable returns (uint32 messageNonce, bytes32 messageHash);\n\n    /**\n     * @notice Send a manager message to the destination domain.\n     * @dev This could only be called by AgentManager, which takes care of encoding the calldata payload.\n     * Note: (msgOrigin, proofMaturity) security args will be added to payload on the destination chain\n     * so that the AgentManager could verify where the Manager Message came from and how mature is the proof.\n     * Note: function is not payable, as no tips are required for sending a manager message.\n     * Will revert if `destination` is equal to contract's local domain.\n     * @param destination           Domain of destination chain\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param payload               Payload for calling AgentManager on destination chain (with extra security args)\n     */\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        returns (uint32 messageNonce, bytes32 messageHash);\n\n    // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Withdraws locked base message tips to the recipient.\n     * @dev Could only be called by a local AgentManager.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function withdrawTips(address recipient, uint256 amount) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the minimum tips value for sending a message to a given destination.\n     * @dev Using at least `tipsValue` as `msg.value` for `sendBaseMessage()`\n     * will guarantee that the message will be accepted.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return tipsValue        Minimum tips value for a message to be accepted\n     */\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue);\n}\n\n// contracts/libs/Constants.sol\n\n// Here we define common constants to enable their easier reusing later.\n\n// ══════════════════════════════════ MERKLE ═══════════════════════════════════\n/// @dev Height of the Agent Merkle Tree\nuint256 constant AGENT_TREE_HEIGHT = 32;\n/// @dev Height of the Origin Merkle Tree\nuint256 constant ORIGIN_TREE_HEIGHT = 32;\n/// @dev Height of the Snapshot Merkle Tree. Allows up to 64 leafs, e.g. up to 32 states\nuint256 constant SNAPSHOT_TREE_HEIGHT = 6;\n// ══════════════════════════════════ STRUCTS ══════════════════════════════════\n/// @dev See Attestation.sol: (bytes32,bytes32,uint32,uint40,uint40): 32+32+4+5+5\nuint256 constant ATTESTATION_LENGTH = 78;\n/// @dev See GasData.sol: (uint16,uint16,uint16,uint16,uint16,uint16): 2+2+2+2+2+2\nuint256 constant GAS_DATA_LENGTH = 12;\n/// @dev See Receipt.sol: (uint32,uint32,bytes32,bytes32,uint8,address,address,address): 4+4+32+32+1+20+20+20\nuint256 constant RECEIPT_LENGTH = 133;\n/// @dev See State.sol: (bytes32,uint32,uint32,uint40,uint40,GasData): 32+4+4+5+5+len(GasData)\nuint256 constant STATE_LENGTH = 50 + GAS_DATA_LENGTH;\n/// @dev Maximum amount of states in a single snapshot. Each state produces two leafs in the tree\nuint256 constant SNAPSHOT_MAX_STATES = 1 \u003c\u003c (SNAPSHOT_TREE_HEIGHT - 1);\n// ══════════════════════════════════ MESSAGE ══════════════════════════════════\n/// @dev See Header.sol: (uint8,uint32,uint32,uint32,uint32): 1+4+4+4+4\nuint256 constant HEADER_LENGTH = 17;\n/// @dev See Request.sol: (uint96,uint64,uint32): 12+8+4\nuint256 constant REQUEST_LENGTH = 24;\n/// @dev See Tips.sol: (uint64,uint64,uint64,uint64): 8+8+8+8\nuint256 constant TIPS_LENGTH = 32;\n/// @dev The amount of discarded last bits when encoding tip values\nuint256 constant TIPS_GRANULARITY = 32;\n/// @dev Tip values could be only the multiples of TIPS_MULTIPLIER\nuint256 constant TIPS_MULTIPLIER = 1 \u003c\u003c TIPS_GRANULARITY;\n// ══════════════════════════════ STATEMENT SALTS ══════════════════════════════\n/// @dev Salts for signing various statements\nbytes32 constant ATTESTATION_VALID_SALT = keccak256(\"ATTESTATION_VALID_SALT\");\nbytes32 constant ATTESTATION_INVALID_SALT = keccak256(\"ATTESTATION_INVALID_SALT\");\nbytes32 constant RECEIPT_VALID_SALT = keccak256(\"RECEIPT_VALID_SALT\");\nbytes32 constant RECEIPT_INVALID_SALT = keccak256(\"RECEIPT_INVALID_SALT\");\nbytes32 constant SNAPSHOT_VALID_SALT = keccak256(\"SNAPSHOT_VALID_SALT\");\nbytes32 constant STATE_INVALID_SALT = keccak256(\"STATE_INVALID_SALT\");\n// ═════════════════════════════════ PROTOCOL ══════════════════════════════════\n/// @dev Optimistic period for new agent roots in LightManager\nuint32 constant AGENT_ROOT_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Timeout between the agent root could be proposed and resolved in LightManager\nuint32 constant AGENT_ROOT_PROPOSAL_TIMEOUT = 12 hours;\nuint32 constant BONDING_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Amount of time that the Notary will not be considered active after they won a dispute\nuint32 constant DISPUTE_TIMEOUT_NOTARY = 12 hours;\n/// @dev Amount of time without fresh data from Notaries before contract owner can resolve stuck disputes manually\nuint256 constant FRESH_DATA_TIMEOUT = 4 hours;\n/// @dev Maximum bytes per message = 2 KiB (somewhat arbitrarily set to begin)\nuint256 constant MAX_CONTENT_BYTES = 2 * 2 ** 10;\n/// @dev Maximum value for the summit tip that could be set in GasOracle\nuint256 constant MAX_SUMMIT_TIP = 0.01 ether;\n\n// contracts/libs/Errors.sol\n\n// ══════════════════════════════ INVALID CALLER ═══════════════════════════════\n\nerror CallerNotAgentManager();\nerror CallerNotDestination();\nerror CallerNotInbox();\nerror CallerNotSummit();\n\n// ══════════════════════════════ INCORRECT DATA ═══════════════════════════════\n\nerror IncorrectAttestation();\nerror IncorrectAgentDomain();\nerror IncorrectAgentIndex();\nerror IncorrectAgentProof();\nerror IncorrectAgentRoot();\nerror IncorrectDataHash();\nerror IncorrectDestinationDomain();\nerror IncorrectOriginDomain();\nerror IncorrectSnapshotProof();\nerror IncorrectSnapshotRoot();\nerror IncorrectState();\nerror IncorrectStatesAmount();\nerror IncorrectTipsProof();\nerror IncorrectVersionLength();\n\nerror IncorrectNonce();\nerror IncorrectSender();\nerror IncorrectRecipient();\n\nerror FlagOutOfRange();\nerror IndexOutOfRange();\nerror NonceOutOfRange();\n\nerror OutdatedNonce();\n\nerror UnformattedAttestation();\nerror UnformattedAttestationReport();\nerror UnformattedBaseMessage();\nerror UnformattedCallData();\nerror UnformattedCallDataPrefix();\nerror UnformattedMessage();\nerror UnformattedReceipt();\nerror UnformattedReceiptReport();\nerror UnformattedSignature();\nerror UnformattedSnapshot();\nerror UnformattedState();\nerror UnformattedStateReport();\n\n// ═══════════════════════════════ MERKLE TREES ════════════════════════════════\n\nerror LeafNotProven();\nerror MerkleTreeFull();\nerror NotEnoughLeafs();\nerror TreeHeightTooLow();\n\n// ═════════════════════════════ OPTIMISTIC PERIOD ═════════════════════════════\n\nerror BaseClientOptimisticPeriod();\nerror MessageOptimisticPeriod();\nerror SlashAgentOptimisticPeriod();\nerror WithdrawTipsOptimisticPeriod();\nerror ZeroProofMaturity();\n\n// ═══════════════════════════════ AGENT MANAGER ═══════════════════════════════\n\nerror AgentNotGuard();\nerror AgentNotNotary();\n\nerror AgentCantBeAdded();\nerror AgentNotActive();\nerror AgentNotActiveNorUnstaking();\nerror AgentNotFraudulent();\nerror AgentNotUnstaking();\nerror AgentUnknown();\n\nerror AgentRootNotProposed();\nerror AgentRootTimeoutNotOver();\n\nerror NotStuck();\n\nerror DisputeAlreadyResolved();\nerror DisputeNotOpened();\nerror DisputeTimeoutNotOver();\nerror GuardInDispute();\nerror NotaryInDispute();\n\nerror MustBeSynapseDomain();\nerror SynapseDomainForbidden();\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\nerror AlreadyExecuted();\nerror AlreadyFailed();\nerror DuplicatedSnapshotRoot();\nerror IncorrectMagicValue();\nerror GasLimitTooLow();\nerror GasSuppliedTooLow();\n\n// ══════════════════════════════════ ORIGIN ═══════════════════════════════════\n\nerror ContentLengthTooBig();\nerror EthTransferFailed();\nerror InsufficientEthBalance();\n\n// ════════════════════════════════ GAS ORACLE ═════════════════════════════════\n\nerror LocalGasDataNotSet();\nerror RemoteGasDataNotSet();\n\n// ═══════════════════════════════════ TIPS ════════════════════════════════════\n\nerror SummitTipTooHigh();\nerror TipsClaimMoreThanEarned();\nerror TipsClaimZero();\nerror TipsOverflow();\nerror TipsValueTooLow();\n\n// ════════════════════════════════ MEMORY VIEW ════════════════════════════════\n\nerror IndexedTooMuch();\nerror ViewOverrun();\nerror OccupiedMemory();\nerror UnallocatedMemory();\nerror PrecompileOutOfGas();\n\n// ═════════════════════════════════ MULTICALL ═════════════════════════════════\n\nerror MulticallFailed();\n\n// contracts/libs/TypeCasts.sol\n\nlibrary TypeCasts {\n    // alignment preserving cast\n    function addressToBytes32(address addr) internal pure returns (bytes32) {\n        return bytes32(uint256(uint160(addr)));\n    }\n\n    // alignment preserving cast\n    function bytes32ToAddress(bytes32 buf) internal pure returns (address) {\n        return address(uint160(uint256(buf)));\n    }\n}\n\n// contracts/libs/stack/Number.sol\n\n/// Number is a compact representation of uint256, that is fit into 16 bits\n/// with the maximum relative error under 0.4%.\ntype Number is uint16;\n\nusing NumberLib for Number global;\n\n/// # Number\n/// Library for compact representation of uint256 numbers.\n/// - Number is stored using mantissa and exponent, each occupying 8 bits.\n/// - Numbers under 2**8 are stored as `mantissa` with `exponent = 0xFF`.\n/// - Numbers at least 2**8 are approximated as `(256 + mantissa) \u003c\u003c exponent`\n/// \u003e - `0 \u003c= mantissa \u003c 256`\n/// \u003e - `0 \u003c= exponent \u003c= 247` (`256 * 2**248` doesn't fit into uint256)\n/// # Number stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type  | Bytes |\n/// | ---------- | -------- | ----- | ----- |\n/// | (002..001] | mantissa | uint8 | 1     |\n/// | (001..000] | exponent | uint8 | 1     |\n\nlibrary NumberLib {\n    /// @dev Amount of bits to shift to mantissa field\n    uint16 private constant SHIFT_MANTISSA = 8;\n\n    /// @notice For bwad math (binary wad) we use 2**64 as \"wad\" unit.\n    /// @dev We are using not using 10**18 as wad, because it is not stored precisely in NumberLib.\n    uint256 internal constant BWAD_SHIFT = 64;\n    uint256 internal constant BWAD = 1 \u003c\u003c BWAD_SHIFT;\n    /// @notice ~0.1% in bwad units.\n    uint256 internal constant PER_MILLE_SHIFT = BWAD_SHIFT - 10;\n    uint256 internal constant PER_MILLE = 1 \u003c\u003c PER_MILLE_SHIFT;\n\n    /// @notice Compresses uint256 number into 16 bits.\n    function compress(uint256 value) internal pure returns (Number) {\n        // Find `msb` such as `2**msb \u003c= value \u003c 2**(msb + 1)`\n        uint256 msb = mostSignificantBit(value);\n        // We want to preserve 9 bits of precision.\n        // The highest bit is always 1, so we can skip it.\n        // The remaining 8 highest bits are stored as mantissa.\n        if (msb \u003c 8) {\n            // Value is less than 2**8, so we can use value as mantissa with \"-1\" exponent.\n            return _encode(uint8(value), 0xFF);\n        } else {\n            // We use `msb - 8` as exponent otherwise. Note that `exponent \u003e= 0`.\n            unchecked {\n                uint256 exponent = msb - 8;\n                // Shifting right by `msb-8` bits will shift the \"remaining 8 highest bits\" into the 8 lowest bits.\n                // uint8() will truncate the highest bit.\n                return _encode(uint8(value \u003e\u003e exponent), uint8(exponent));\n            }\n        }\n    }\n\n    /// @notice Decompresses 16 bits number into uint256.\n    /// @dev The outcome is an approximation of the original number: `(value - value / 256) \u003c number \u003c= value`.\n    function decompress(Number number) internal pure returns (uint256 value) {\n        // Isolate 8 highest bits as the mantissa.\n        uint256 mantissa = Number.unwrap(number) \u003e\u003e SHIFT_MANTISSA;\n        // This will truncate the highest bits, leaving only the exponent.\n        uint256 exponent = uint8(Number.unwrap(number));\n        if (exponent == 0xFF) {\n            return mantissa;\n        } else {\n            unchecked {\n                return (256 + mantissa) \u003c\u003c (exponent);\n            }\n        }\n    }\n\n    /// @dev Returns the most significant bit of `x`\n    /// https://solidity-by-example.org/bitwise/\n    function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\n        // To find `msb` we determine it bit by bit, starting from the highest one.\n        // `0 \u003c= msb \u003c= 255`, so we start from the highest bit, 1\u003c\u003c7 == 128.\n        // If `x` is at least 2**128, then the highest bit of `x` is at least 128.\n        // solhint-disable no-inline-assembly\n        assembly {\n            // `f` is set to 1\u003c\u003c7 if `x \u003e= 2**128` and to 0 otherwise.\n            let f := shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\n            // If `x \u003e= 2**128` then set `msb` highest bit to 1 and shift `x` right by 128.\n            // Otherwise, `msb` remains 0 and `x` remains unchanged.\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        // `x` is now at most 2**128 - 1. Continue the same way, the next highest bit is 1\u003c\u003c6 == 64.\n        assembly {\n            // `f` is set to 1\u003c\u003c6 if `x \u003e= 2**64` and to 0 otherwise.\n            let f := shl(6, gt(x, 0xFFFFFFFFFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c5 if `x \u003e= 2**32` and to 0 otherwise.\n            let f := shl(5, gt(x, 0xFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c4 if `x \u003e= 2**16` and to 0 otherwise.\n            let f := shl(4, gt(x, 0xFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c3 if `x \u003e= 2**8` and to 0 otherwise.\n            let f := shl(3, gt(x, 0xFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c2 if `x \u003e= 2**4` and to 0 otherwise.\n            let f := shl(2, gt(x, 0xF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c1 if `x \u003e= 2**2` and to 0 otherwise.\n            let f := shl(1, gt(x, 0x3))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1 if `x \u003e= 2**1` and to 0 otherwise.\n            let f := gt(x, 0x1)\n            msb := or(msb, f)\n        }\n    }\n\n    /// @dev Wraps (mantissa, exponent) pair into Number.\n    function _encode(uint8 mantissa, uint8 exponent) private pure returns (Number) {\n        // Casts below are upcasts, so they are safe.\n        return Number.wrap(uint16(mantissa) \u003c\u003c SHIFT_MANTISSA | uint16(exponent));\n    }\n}\n\n// contracts/libs/stack/Request.sol\n\n/// Request is encoded data with \"message execution request\".\ntype Request is uint192;\n\nusing RequestLib for Request global;\n\n/// Library for formatting _the request part_ of _the base messages_.\n/// - Request represents a message sender requirements for the message execution on the destination chain.\n/// - Request occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n/// \u003e gasDrop field is included for future compatibility and is ignored at the moment.\n///\n/// # Request stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type   | Bytes | Description                                          |\n/// | ---------- | -------- | ------ | ----- | ---------------------------------------------------- |\n/// | (024..012] | gasDrop  | uint96 | 12    | Minimum amount of gas token to drop to the recipient |\n/// | (012..004] | gasLimit | uint64 | 8     | Minimum amount of gas units to supply for execution  |\n/// | (004..000] | version  | uint32 | 4     | Base message version to pass to the recipient        |\n\nlibrary RequestLib {\n    /// @dev Amount of bits to shift to gasDrop field\n    uint192 private constant SHIFT_GAS_DROP = 12 * 8;\n    /// @dev Amount of bits to shift to gasLimit field\n    uint192 private constant SHIFT_GAS_LIMIT = 4 * 8;\n\n    /// @notice Returns an encoded request with the given fields\n    /// @param gasDrop_     Minimum amount of gas token to drop to the recipient (ignored at the moment)\n    /// @param gasLimit_    Minimum amount of gas units to supply for execution\n    /// @param version_     Base message version to pass to the recipient\n    function encodeRequest(uint96 gasDrop_, uint64 gasLimit_, uint32 version_) internal pure returns (Request) {\n        // Casts below are upcasts, so they are safe\n        return Request.wrap(uint192(gasDrop_) \u003c\u003c SHIFT_GAS_DROP | uint192(gasLimit_) \u003c\u003c SHIFT_GAS_LIMIT | version_);\n    }\n\n    /// @notice Wraps the padded encoded request into a Request-typed value.\n    /// @dev The \"padded\" request is simply an encoded request casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded requests\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedRequest) internal pure returns (Request) {\n        // Casting to uint192 will truncate the highest bits, which is the behavior we want\n        return Request.wrap(uint192(paddedRequest));\n    }\n\n    /// @notice Returns the requested of gas token to drop to the recipient.\n    function gasDrop(Request request) internal pure returns (uint96) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return uint96(Request.unwrap(request) \u003e\u003e SHIFT_GAS_DROP);\n    }\n\n    /// @notice Returns the requested minimum amount of gas units to supply for execution.\n    function gasLimit(Request request) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Request.unwrap(request) \u003e\u003e SHIFT_GAS_LIMIT);\n    }\n\n    /// @notice Returns the requested base message version to pass to the recipient.\n    function version(Request request) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Request.unwrap(request));\n    }\n}\n\n// node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        require(value \u003c= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        require(value \u003c= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        require(value \u003c= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value \u003c= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        require(value \u003c= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        require(value \u003c= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        require(value \u003c= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        require(value \u003c= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        require(value \u003c= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        require(value \u003c= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        require(value \u003c= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        require(value \u003c= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        require(value \u003c= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        require(value \u003c= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        require(value \u003c= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value \u003c= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        require(value \u003c= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        require(value \u003c= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        require(value \u003c= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value \u003c= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        require(value \u003c= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        require(value \u003c= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        require(value \u003c= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value \u003c= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        require(value \u003c= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        require(value \u003c= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        require(value \u003c= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value \u003c= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        require(value \u003c= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value \u003c= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value \u003c= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     *\n     * _Available since v3.0._\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value \u003e= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     *\n     * _Available since v3.0._\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value \u003c= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     *\n     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length \u003e 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance \u003e= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance \u003e= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length \u003e 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n\n// contracts/base/MultiCallable.sol\n\n/// @notice Collection of Multicall utilities. Fork of Multicall3:\n/// https://github.com/mds1/multicall/blob/master/src/Multicall3.sol\nabstract contract MultiCallable {\n    struct Call {\n        bool allowFailure;\n        bytes callData;\n    }\n\n    struct Result {\n        bool success;\n        bytes returnData;\n    }\n\n    /// @notice Aggregates a few calls to this contract into one multicall without modifying `msg.sender`.\n    function multicall(Call[] calldata calls) external returns (Result[] memory callResults) {\n        uint256 amount = calls.length;\n        callResults = new Result[](amount);\n        Call calldata call_;\n        for (uint256 i = 0; i \u003c amount;) {\n            call_ = calls[i];\n            Result memory result = callResults[i];\n            // We perform a delegate call to ourselves here. Delegate call does not modify `msg.sender`, so\n            // this will have the same effect as if `msg.sender` performed all the calls themselves one by one.\n            // solhint-disable-next-line avoid-low-level-calls\n            (result.success, result.returnData) = address(this).delegatecall(call_.callData);\n            // solhint-disable-next-line no-inline-assembly\n            assembly {\n                // Revert if the call fails and failure is not allowed\n                // `allowFailure := calldataload(call_)` and `success := mload(result)`\n                if iszero(or(calldataload(call_), mload(result))) {\n                    // Revert with `0x4d6a2328` (function selector for `MulticallFailed()`)\n                    mstore(0x00, 0x4d6a232800000000000000000000000000000000000000000000000000000000)\n                    revert(0x00, 0x04)\n                }\n            }\n            unchecked {\n                ++i;\n            }\n        }\n    }\n}\n\n// contracts/base/Version.sol\n\n/**\n * @title Versioned\n * @notice Version getter for contracts. Doesn't use any storage slots, meaning\n * it will never cause any troubles with the upgradeable contracts. For instance, this contract\n * can be added or removed from the inheritance chain without shifting the storage layout.\n */\nabstract contract Versioned {\n    /**\n     * @notice Struct that is mimicking the storage layout of a string with 32 bytes or less.\n     * Length is limited by 32, so the whole string payload takes two memory words:\n     * @param length    String length\n     * @param data      String characters\n     */\n    struct _ShortString {\n        uint256 length;\n        bytes32 data;\n    }\n\n    /// @dev Length of the \"version string\"\n    uint256 private immutable _length;\n    /// @dev Bytes representation of the \"version string\".\n    /// Strings with length over 32 are not supported!\n    bytes32 private immutable _data;\n\n    constructor(string memory version_) {\n        _length = bytes(version_).length;\n        if (_length \u003e 32) revert IncorrectVersionLength();\n        // bytes32 is left-aligned =\u003e this will store the byte representation of the string\n        // with the trailing zeroes to complete the 32-byte word\n        _data = bytes32(bytes(version_));\n    }\n\n    function version() external view returns (string memory versionString) {\n        // Load the immutable values to form the version string\n        _ShortString memory str = _ShortString(_length, _data);\n        // The only way to do this cast is doing some dirty assembly\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            versionString := str\n        }\n    }\n}\n\n// contracts/libs/ChainContext.sol\n\n/// @notice Library for accessing chain context variables as tightly packed integers.\n/// Messaging contracts should rely on this library for accessing chain context variables\n/// instead of doing the casting themselves.\nlibrary ChainContext {\n    using SafeCast for uint256;\n\n    /// @notice Returns the current block number as uint40.\n    /// @dev Reverts if block number is greater than 40 bits, which is not supposed to happen\n    /// until the block.timestamp overflows (assuming block time is at least 1 second).\n    function blockNumber() internal view returns (uint40) {\n        return block.number.toUint40();\n    }\n\n    /// @notice Returns the current block timestamp as uint40.\n    /// @dev Reverts if block timestamp is greater than 40 bits, which is\n    /// supposed to happen approximately in year 36835.\n    function blockTimestamp() internal view returns (uint40) {\n        return block.timestamp.toUint40();\n    }\n\n    /// @notice Returns the chain id as uint32.\n    /// @dev Reverts if chain id is greater than 32 bits, which is not\n    /// supposed to happen in production.\n    function chainId() internal view returns (uint32) {\n        return block.chainid.toUint32();\n    }\n}\n\n// contracts/libs/Structures.sol\n\n// Here we define common enums and structures to enable their easier reusing later.\n\n// ═══════════════════════════════ AGENT STATUS ════════════════════════════════\n\n/// @dev Potential statuses for the off-chain bonded agent:\n/// - Unknown: never provided a bond =\u003e signature not valid\n/// - Active: has a bond in BondingManager =\u003e signature valid\n/// - Unstaking: has a bond in BondingManager, initiated the unstaking =\u003e signature not valid\n/// - Resting: used to have a bond in BondingManager, successfully unstaked =\u003e signature not valid\n/// - Fraudulent: proven to commit fraud, value in Merkle Tree not updated =\u003e signature not valid\n/// - Slashed: proven to commit fraud, value in Merkle Tree was updated =\u003e signature not valid\n/// Unstaked agent could later be added back to THE SAME domain by staking a bond again.\n/// Honest agent: Unknown -\u003e Active -\u003e unstaking -\u003e Resting -\u003e Active ...\n/// Malicious agent: Unknown -\u003e Active -\u003e Fraudulent -\u003e Slashed\n/// Malicious agent: Unknown -\u003e Active -\u003e Unstaking -\u003e Fraudulent -\u003e Slashed\nenum AgentFlag {\n    Unknown,\n    Active,\n    Unstaking,\n    Resting,\n    Fraudulent,\n    Slashed\n}\n\n/// @notice Struct for storing an agent in the BondingManager contract.\nstruct AgentStatus {\n    AgentFlag flag;\n    uint32 domain;\n    uint32 index;\n}\n// 184 bits available for tight packing\n\nusing StructureUtils for AgentStatus global;\n\n/// @notice Potential statuses of an agent in terms of being in dispute\n/// - None: agent is not in dispute\n/// - Pending: agent is in unresolved dispute\n/// - Slashed: agent was in dispute that lead to agent being slashed\n/// Note: agent who won the dispute has their status reset to None\nenum DisputeFlag {\n    None,\n    Pending,\n    Slashed\n}\n\n/// @notice Struct for storing dispute status of an agent.\n/// @param flag         Dispute flag: None/Pending/Slashed.\n/// @param openedAt     Timestamp when the latest agent dispute was opened (zero if not opened).\n/// @param resolvedAt   Timestamp when the latest agent dispute was resolved (zero if not resolved).\nstruct DisputeStatus {\n    DisputeFlag flag;\n    uint40 openedAt;\n    uint40 resolvedAt;\n}\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\n/// @notice Struct representing the status of Destination contract.\n/// @param snapRootTime     Timestamp when latest snapshot root was accepted\n/// @param agentRootTime    Timestamp when latest agent root was accepted\n/// @param notaryIndex      Index of Notary who signed the latest agent root\nstruct DestinationStatus {\n    uint40 snapRootTime;\n    uint40 agentRootTime;\n    uint32 notaryIndex;\n}\n\n// ═══════════════════════════════ EXECUTION HUB ═══════════════════════════════\n\n/// @notice Potential statuses of the message in Execution Hub.\n/// - None: there hasn't been a valid attempt to execute the message yet\n/// - Failed: there was a valid attempt to execute the message, but recipient reverted\n/// - Success: there was a valid attempt to execute the message, and recipient did not revert\n/// Note: message can be executed until its status is Success\nenum MessageStatus {\n    None,\n    Failed,\n    Success\n}\n\nlibrary StructureUtils {\n    /// @notice Checks that Agent is Active\n    function verifyActive(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active) {\n            revert AgentNotActive();\n        }\n    }\n\n    /// @notice Checks that Agent is Unstaking\n    function verifyUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Unstaking) {\n            revert AgentNotUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Active or Unstaking\n    function verifyActiveUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active \u0026\u0026 status.flag != AgentFlag.Unstaking) {\n            revert AgentNotActiveNorUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Fraudulent\n    function verifyFraudulent(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Fraudulent) {\n            revert AgentNotFraudulent();\n        }\n    }\n\n    /// @notice Checks that Agent is not Unknown\n    function verifyKnown(AgentStatus memory status) internal pure {\n        if (status.flag == AgentFlag.Unknown) {\n            revert AgentUnknown();\n        }\n    }\n}\n\n// contracts/libs/memory/MemView.sol\n\n/// @dev MemView is an untyped view over a portion of memory to be used instead of `bytes memory`\ntype MemView is uint256;\n\n/// @dev Attach library functions to MemView\nusing MemViewLib for MemView global;\n\n/// @notice Library for operations with the memory views.\n/// Forked from https://github.com/summa-tx/memview-sol with several breaking changes:\n/// - The codebase is ported to Solidity 0.8\n/// - Custom errors are added\n/// - The runtime type checking is replaced with compile-time check provided by User-Defined Value Types\n///   https://docs.soliditylang.org/en/latest/types.html#user-defined-value-types\n/// - uint256 is used as the underlying type for the \"memory view\" instead of bytes29.\n///   It is wrapped into MemView custom type in order not to be confused with actual integers.\n/// - Therefore the \"type\" field is discarded, allowing to allocate 16 bytes for both view location and length\n/// - The documentation is expanded\n/// - Library functions unused by the rest of the codebase are removed\n//  - Very pretty code separators are added :)\nlibrary MemViewLib {\n    /// @notice Stack layout for uint256 (from highest bits to lowest)\n    /// (32 .. 16]      loc     16 bytes    Memory address of underlying bytes\n    /// (16 .. 00]      len     16 bytes    Length of underlying bytes\n\n    // ═══════════════════════════════════════════ BUILDING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Instantiate a new untyped memory view. This should generally not be called directly.\n     * Prefer `ref` wherever possible.\n     * @param loc_          The memory address\n     * @param len_          The length\n     * @return The new view with the specified location and length\n     */\n    function build(uint256 loc_, uint256 len_) internal pure returns (MemView) {\n        uint256 end_ = loc_ + len_;\n        // Make sure that a view is not constructed that points to unallocated memory\n        // as this could be indicative of a buffer overflow attack\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            if gt(end_, mload(0x40)) { end_ := 0 }\n        }\n        if (end_ == 0) {\n            revert UnallocatedMemory();\n        }\n        return _unsafeBuildUnchecked(loc_, len_);\n    }\n\n    /**\n     * @notice Instantiate a memory view from a byte array.\n     * @dev Note that due to Solidity memory representation, it is not possible to\n     * implement a deref, as the `bytes` type stores its len in memory.\n     * @param arr           The byte array\n     * @return The memory view over the provided byte array\n     */\n    function ref(bytes memory arr) internal pure returns (MemView) {\n        uint256 len_ = arr.length;\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 loc_;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // We add 0x20, so that the view starts exactly where the array data starts\n            loc_ := add(arr, 0x20)\n        }\n        return build(loc_, len_);\n    }\n\n    // ════════════════════════════════════════════ CLONING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to the new memory.\n     * @param memView       The memory view\n     * @return arr          The cloned byte array\n     */\n    function clone(MemView memView) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        unchecked {\n            _unsafeCopyTo(memView, ptr + 0x20);\n        }\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 len_ = memView.len();\n        uint256 footprint_ = memView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    /**\n     * @notice Copies all views, joins them into a new bytearray.\n     * @param memViews      The memory views\n     * @return arr          The new byte array with joined data behind the given views\n     */\n    function join(MemView[] memory memViews) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        MemView newView;\n        unchecked {\n            newView = _unsafeJoin(memViews, ptr + 0x20);\n        }\n        uint256 len_ = newView.len();\n        uint256 footprint_ = newView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    // ══════════════════════════════════════════ INSPECTING MEMORY VIEW ═══════════════════════════════════════════════\n\n    /**\n     * @notice Returns the memory address of the underlying bytes.\n     * @param memView       The memory view\n     * @return loc_         The memory address\n     */\n    function loc(MemView memView) internal pure returns (uint256 loc_) {\n        // loc is stored in the highest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u003e\u003e 128;\n    }\n\n    /**\n     * @notice Returns the number of bytes of the view.\n     * @param memView       The memory view\n     * @return len_         The length of the view\n     */\n    function len(MemView memView) internal pure returns (uint256 len_) {\n        // len is stored in the lowest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u0026 type(uint128).max;\n    }\n\n    /**\n     * @notice Returns the endpoint of `memView`.\n     * @param memView       The memory view\n     * @return end_         The endpoint of `memView`\n     */\n    function end(MemView memView) internal pure returns (uint256 end_) {\n        // The endpoint never overflows uint128, let alone uint256, so we could use unchecked math here\n        unchecked {\n            return memView.loc() + memView.len();\n        }\n    }\n\n    /**\n     * @notice Returns the number of memory words this memory view occupies, rounded up.\n     * @param memView       The memory view\n     * @return words_       The number of memory words\n     */\n    function words(MemView memView) internal pure returns (uint256 words_) {\n        // returning ceil(length / 32.0)\n        unchecked {\n            return (memView.len() + 31) \u003e\u003e 5;\n        }\n    }\n\n    /**\n     * @notice Returns the in-memory footprint of a fresh copy of the view.\n     * @param memView       The memory view\n     * @return footprint_   The in-memory footprint of a fresh copy of the view.\n     */\n    function footprint(MemView memView) internal pure returns (uint256 footprint_) {\n        // words() * 32\n        return memView.words() \u003c\u003c 5;\n    }\n\n    // ════════════════════════════════════════════ HASHING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the keccak256 hash of the underlying memory\n     * @param memView       The memory view\n     * @return digest       The keccak256 hash of the underlying memory\n     */\n    function keccak(MemView memView) internal pure returns (bytes32 digest) {\n        uint256 loc_ = memView.loc();\n        uint256 len_ = memView.len();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            digest := keccak256(loc_, len_)\n        }\n    }\n\n    /**\n     * @notice Adds a salt to the keccak256 hash of the underlying data and returns the keccak256 hash of the\n     * resulting data.\n     * @param memView       The memory view\n     * @return digestSalted keccak256(salt, keccak256(memView))\n     */\n    function keccakSalted(MemView memView, bytes32 salt) internal pure returns (bytes32 digestSalted) {\n        return keccak256(bytes.concat(salt, memView.keccak()));\n    }\n\n    // ════════════════════════════════════════════ SLICING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Safe slicing without memory modification.\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the given index\n     */\n    function slice(MemView memView, uint256 index_, uint256 len_) internal pure returns (MemView) {\n        uint256 loc_ = memView.loc();\n        // Ensure it doesn't overrun the view\n        if (loc_ + index_ + len_ \u003e memView.end()) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // loc_ + index_ \u003c= memView.end()\n            return build({loc_: loc_ + index_, len_: len_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing bytes from `index` to end(memView).\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @return The new view for the slice starting from the given index until the initial view endpoint\n     */\n    function sliceFrom(MemView memView, uint256 index_) internal pure returns (MemView) {\n        uint256 len_ = memView.len();\n        // Ensure it doesn't overrun the view\n        if (index_ \u003e len_) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // index_ \u003c= len_ =\u003e memView.loc() + index_ \u003c= memView.loc() + memView.len() == memView.end()\n            return build({loc_: memView.loc() + index_, len_: len_ - index_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the first `len` bytes.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the initial view beginning\n     */\n    function prefix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        return memView.slice({index_: 0, len_: len_});\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the last `len` byte.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length until the initial view endpoint\n     */\n    function postfix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        uint256 viewLen = memView.len();\n        // Ensure it doesn't overrun the view\n        if (len_ \u003e viewLen) {\n            revert ViewOverrun();\n        }\n        // Could do the unchecked math due to the check above\n        uint256 index_;\n        unchecked {\n            index_ = viewLen - len_;\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // len_ \u003c= memView.len() =\u003e memView.loc() \u003c= loc_ \u003c= memView.end()\n            return build({loc_: memView.loc() + viewLen - len_, len_: len_});\n        }\n    }\n\n    // ═══════════════════════════════════════════ INDEXING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Load up to 32 bytes from the view onto the stack.\n     * @dev Returns a bytes32 with only the `bytes_` HIGHEST bytes set.\n     * This can be immediately cast to a smaller fixed-length byte array.\n     * To automatically cast to an integer, use `indexUint`.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return result       The 32 byte result having only `bytes_` highest bytes set\n     */\n    function index(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (bytes32 result) {\n        if (bytes_ == 0) {\n            return bytes32(0);\n        }\n        // Can't load more than 32 bytes to the stack in one go\n        if (bytes_ \u003e 32) {\n            revert IndexedTooMuch();\n        }\n        // The last indexed byte should be within view boundaries\n        if (index_ + bytes_ \u003e memView.len()) {\n            revert ViewOverrun();\n        }\n        uint256 bitLength = bytes_ \u003c\u003c 3; // bytes_ * 8\n        uint256 loc_ = memView.loc();\n        // Get a mask with `bitLength` highest bits set\n        uint256 mask;\n        // 0x800...00 binary representation is 100...00\n        // sar stands for \"signed arithmetic shift\": https://en.wikipedia.org/wiki/Arithmetic_shift\n        // sar(N-1, 100...00) = 11...100..00, with exactly N highest bits set to 1\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            mask := sar(sub(bitLength, 1), 0x8000000000000000000000000000000000000000000000000000000000000000)\n        }\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load a full word using index offset, and apply mask to ignore non-relevant bytes\n            result := and(mload(add(loc_, index_)), mask)\n        }\n    }\n\n    /**\n     * @notice Parse an unsigned integer from the view at `index`.\n     * @dev Requires that the view have \u003e= `bytes_` bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return The unsigned integer\n     */\n    function indexUint(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (uint256) {\n        bytes32 indexedBytes = memView.index(index_, bytes_);\n        // `index()` returns left-aligned `bytes_`, while integers are right-aligned\n        // Shifting here to right-align with the full 32 bytes word: need to shift right `(32 - bytes_)` bytes\n        unchecked {\n            // memView.index() reverts when bytes_ \u003e 32, thus unchecked math\n            return uint256(indexedBytes) \u003e\u003e ((32 - bytes_) \u003c\u003c 3);\n        }\n    }\n\n    /**\n     * @notice Parse an address from the view at `index`.\n     * @dev Requires that the view have \u003e= 20 bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @return The address\n     */\n    function indexAddress(MemView memView, uint256 index_) internal pure returns (address) {\n        // index 20 bytes as `uint160`, and then cast to `address`\n        return address(uint160(memView.indexUint(index_, 20)));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns a memory view over the specified memory location\n    /// without checking if it points to unallocated memory.\n    function _unsafeBuildUnchecked(uint256 loc_, uint256 len_) private pure returns (MemView) {\n        // There is no scenario where loc or len would overflow uint128, so we omit this check.\n        // We use the highest 128 bits to encode the location and the lowest 128 bits to encode the length.\n        return MemView.wrap((loc_ \u003c\u003c 128) | len_);\n    }\n\n    /**\n     * @notice Copy the view to a location, return an unsafe memory reference\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memView       The memory view\n     * @param newLoc        The new location to copy the underlying view data\n     * @return The memory view over the unsafe memory with the copied underlying data\n     */\n    function _unsafeCopyTo(MemView memView, uint256 newLoc) private view returns (MemView) {\n        uint256 len_ = memView.len();\n        uint256 oldLoc = memView.loc();\n\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (newLoc \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        bool res;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // use the identity precompile (0x04) to copy\n            res := staticcall(gas(), 0x04, oldLoc, len_, newLoc, len_)\n        }\n        if (!res) revert PrecompileOutOfGas();\n        return _unsafeBuildUnchecked({loc_: newLoc, len_: len_});\n    }\n\n    /**\n     * @notice Join the views in memory, return an unsafe reference to the memory.\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memViews      The memory views\n     * @return The conjoined view pointing to the new memory\n     */\n    function _unsafeJoin(MemView[] memory memViews, uint256 location) private view returns (MemView) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (location \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        // Copy the views to the specified location one by one, by tracking the amount of copied bytes so far\n        uint256 offset = 0;\n        for (uint256 i = 0; i \u003c memViews.length;) {\n            MemView memView = memViews[i];\n            // We can use the unchecked math here as location + sum(view.length) will never overflow uint256\n            unchecked {\n                _unsafeCopyTo(memView, location + offset);\n                offset += memView.len();\n                ++i;\n            }\n        }\n        return _unsafeBuildUnchecked({loc_: location, len_: offset});\n    }\n}\n\n// contracts/libs/merkle/MerkleMath.sol\n\nlibrary MerkleMath {\n    // ═════════════════════════════════════════ BASIC MERKLE CALCULATIONS ═════════════════════════════════════════════\n\n    /**\n     * @notice Calculates the merkle root for the given leaf and merkle proof.\n     * @dev Will revert if proof length exceeds the tree height.\n     * @param index     Index of `leaf` in tree\n     * @param leaf      Leaf of the merkle tree\n     * @param proof     Proof of inclusion of `leaf` in the tree\n     * @param height    Height of the merkle tree\n     * @return root_    Calculated Merkle Root\n     */\n    function proofRoot(uint256 index, bytes32 leaf, bytes32[] memory proof, uint256 height)\n        internal\n        pure\n        returns (bytes32 root_)\n    {\n        // Proof length could not exceed the tree height\n        uint256 proofLen = proof.length;\n        if (proofLen \u003e height) revert TreeHeightTooLow();\n        root_ = leaf;\n        /// @dev Apply unchecked to all ++h operations\n        unchecked {\n            // Go up the tree levels from the leaf following the proof\n            for (uint256 h = 0; h \u003c proofLen; ++h) {\n                // Get a sibling node on current level: this is proof[h]\n                root_ = getParent(root_, proof[h], index, h);\n            }\n            // Go up to the root: the remaining siblings are EMPTY\n            for (uint256 h = proofLen; h \u003c height; ++h) {\n                root_ = getParent(root_, bytes32(0), index, h);\n            }\n        }\n    }\n\n    /**\n     * @notice Calculates the parent of a node on the path from one of the leafs to root.\n     * @param node          Node on a path from tree leaf to root\n     * @param sibling       Sibling for a given node\n     * @param leafIndex     Index of the tree leaf\n     * @param nodeHeight    \"Level height\" for `node` (ZERO for leafs, ORIGIN_TREE_HEIGHT for root)\n     */\n    function getParent(bytes32 node, bytes32 sibling, uint256 leafIndex, uint256 nodeHeight)\n        internal\n        pure\n        returns (bytes32 parent)\n    {\n        // Index for `node` on its \"tree level\" is (leafIndex / 2**height)\n        // \"Left child\" has even index, \"right child\" has odd index\n        if ((leafIndex \u003e\u003e nodeHeight) \u0026 1 == 0) {\n            // Left child\n            return getParent(node, sibling);\n        } else {\n            // Right child\n            return getParent(sibling, node);\n        }\n    }\n\n    /// @notice Calculates the parent of tow nodes in the merkle tree.\n    /// @dev We use implementation with H(0,0) = 0\n    /// This makes EVERY empty node in the tree equal to ZERO,\n    /// saving us from storing H(0,0), H(H(0,0), H(0, 0)), and so on\n    /// @param leftChild    Left child of the calculated node\n    /// @param rightChild   Right child of the calculated node\n    /// @return parent      Value for the node having above mentioned children\n    function getParent(bytes32 leftChild, bytes32 rightChild) internal pure returns (bytes32 parent) {\n        if (leftChild == bytes32(0) \u0026\u0026 rightChild == bytes32(0)) {\n            return 0;\n        } else {\n            return keccak256(bytes.concat(leftChild, rightChild));\n        }\n    }\n\n    // ════════════════════════════════ ROOT/PROOF CALCULATION FOR A LIST OF LEAFS ═════════════════════════════════════\n\n    /**\n     * @notice Calculates merkle root for a list of given leafs.\n     * Merkle Tree is constructed by padding the list with ZERO values for leafs until list length is `2**height`.\n     * Merkle Root is calculated for the constructed tree, and then saved in `leafs[0]`.\n     * \u003e Note:\n     * \u003e - `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * \u003e - Caller is expected not to reuse `hashes` list after the call, and only use `leafs[0]` value,\n     * which is guaranteed to contain the calculated merkle root.\n     * \u003e - root is calculated using the `H(0,0) = 0` Merkle Tree implementation. See MerkleTree.sol for details.\n     * @dev Amount of leaves should be at most `2**height`\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param height    Height of the Merkle Tree to construct\n     */\n    function calculateRoot(bytes32[] memory hashes, uint256 height) internal pure {\n        uint256 levelLength = hashes.length;\n        // Amount of hashes could not exceed amount of leafs in tree with the given height\n        if (levelLength \u003e (1 \u003c\u003c height)) revert TreeHeightTooLow();\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\": the amount of iterations for the for loop above.\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n            }\n        }\n    }\n\n    /**\n     * @notice Generates a proof of inclusion of a leaf in the list. If the requested index is outside\n     * of the list range, generates a proof of inclusion for an empty leaf (proof of non-inclusion).\n     * The Merkle Tree is constructed by padding the list with ZERO values until list length is a power of two\n     * __AND__ index is in the extended list range. For example:\n     *  - `hashes.length == 6` and `0 \u003c= index \u003c= 7` will \"extend\" the list to 8 entries.\n     *  - `hashes.length == 6` and `7 \u003c index \u003c= 15` will \"extend\" the list to 16 entries.\n     * \u003e Note: `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * Caller is expected not to reuse `hashes` list after the call.\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param index     Leaf index to generate the proof for\n     * @return proof    Generated merkle proof\n     */\n    function calculateProof(bytes32[] memory hashes, uint256 index) internal pure returns (bytes32[] memory proof) {\n        // Use only meaningful values for the shortened proof\n        // Check if index is within the list range (we want to generates proofs for outside leafs as well)\n        uint256 height = getHeight(index \u003c hashes.length ? hashes.length : (index + 1));\n        proof = new bytes32[](height);\n        uint256 levelLength = hashes.length;\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Use sibling for the merkle proof; `index^1` is index of our sibling\n                proof[h] = (index ^ 1 \u003c levelLength) ? hashes[index ^ 1] : bytes32(0);\n\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\"\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n                // Traverse to parent node\n                index \u003e\u003e= 1;\n            }\n        }\n    }\n\n    /// @notice Returns the height of the tree having a given amount of leafs.\n    function getHeight(uint256 leafs) internal pure returns (uint256 height) {\n        uint256 amount = 1;\n        while (amount \u003c leafs) {\n            unchecked {\n                ++height;\n            }\n            amount \u003c\u003c= 1;\n        }\n    }\n}\n\n// contracts/libs/stack/GasData.sol\n\n/// GasData in encoded data with \"basic information about gas prices\" for some chain.\ntype GasData is uint96;\n\nusing GasDataLib for GasData global;\n\n/// ChainGas is encoded data with given chain's \"basic information about gas prices\".\ntype ChainGas is uint128;\n\nusing GasDataLib for ChainGas global;\n\n/// Library for encoding and decoding GasData and ChainGas structs.\n/// # GasData\n/// `GasData` is a struct to store the \"basic information about gas prices\", that could\n/// be later used to approximate the cost of a message execution, and thus derive the\n/// minimal tip values for sending a message to the chain.\n/// \u003e - `GasData` is supposed to be cached by `GasOracle` contract, allowing to store the\n/// \u003e approximates instead of the exact values, and thus save on storage costs.\n/// \u003e - For instance, if `GasOracle` only updates the values on +- 10% change, having an\n/// \u003e 0.4% error on the approximates would be acceptable.\n/// `GasData` is supposed to be included in the Origin's state, which are synced across\n/// chains using Agent-signed snapshots and attestations.\n/// ## GasData stack layout (from highest bits to lowest)\n///\n/// | Position   | Field        | Type   | Bytes | Description                                         |\n/// | ---------- | ------------ | ------ | ----- | --------------------------------------------------- |\n/// | (012..010] | gasPrice     | uint16 | 2     | Gas price for the chain (in Wei per gas unit)       |\n/// | (010..008] | dataPrice    | uint16 | 2     | Calldata price (in Wei per byte of content)         |\n/// | (008..006] | execBuffer   | uint16 | 2     | Tx fee safety buffer for message execution (in Wei) |\n/// | (006..004] | amortAttCost | uint16 | 2     | Amortized cost for attestation submission (in Wei)  |\n/// | (004..002] | etherPrice   | uint16 | 2     | Chain's Ether Price / Mainnet Ether Price (in BWAD) |\n/// | (002..000] | markup       | uint16 | 2     | Markup for the message execution (in BWAD)          |\n/// \u003e See Number.sol for more details on `Number` type and BWAD (binary WAD) math.\n///\n/// ## ChainGas stack layout (from highest bits to lowest)\n///\n/// | Position   | Field   | Type   | Bytes | Description      |\n/// | ---------- | ------- | ------ | ----- | ---------------- |\n/// | (016..004] | gasData | uint96 | 12    | Chain's gas data |\n/// | (004..000] | domain  | uint32 | 4     | Chain's domain   |\nlibrary GasDataLib {\n    /// @dev Amount of bits to shift to gasPrice field\n    uint96 private constant SHIFT_GAS_PRICE = 10 * 8;\n    /// @dev Amount of bits to shift to dataPrice field\n    uint96 private constant SHIFT_DATA_PRICE = 8 * 8;\n    /// @dev Amount of bits to shift to execBuffer field\n    uint96 private constant SHIFT_EXEC_BUFFER = 6 * 8;\n    /// @dev Amount of bits to shift to amortAttCost field\n    uint96 private constant SHIFT_AMORT_ATT_COST = 4 * 8;\n    /// @dev Amount of bits to shift to etherPrice field\n    uint96 private constant SHIFT_ETHER_PRICE = 2 * 8;\n\n    /// @dev Amount of bits to shift to gasData field\n    uint128 private constant SHIFT_GAS_DATA = 4 * 8;\n\n    // ═════════════════════════════════════════════════ GAS DATA ══════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded GasData struct with the given fields.\n    /// @param gasPrice_        Gas price for the chain (in Wei per gas unit)\n    /// @param dataPrice_       Calldata price (in Wei per byte of content)\n    /// @param execBuffer_      Tx fee safety buffer for message execution (in Wei)\n    /// @param amortAttCost_    Amortized cost for attestation submission (in Wei)\n    /// @param etherPrice_      Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n    /// @param markup_          Markup for the message execution (in BWAD)\n    function encodeGasData(\n        Number gasPrice_,\n        Number dataPrice_,\n        Number execBuffer_,\n        Number amortAttCost_,\n        Number etherPrice_,\n        Number markup_\n    ) internal pure returns (GasData) {\n        // Number type wraps uint16, so could safely be casted to uint96\n        // forgefmt: disable-next-item\n        return GasData.wrap(\n            uint96(Number.unwrap(gasPrice_)) \u003c\u003c SHIFT_GAS_PRICE |\n            uint96(Number.unwrap(dataPrice_)) \u003c\u003c SHIFT_DATA_PRICE |\n            uint96(Number.unwrap(execBuffer_)) \u003c\u003c SHIFT_EXEC_BUFFER |\n            uint96(Number.unwrap(amortAttCost_)) \u003c\u003c SHIFT_AMORT_ATT_COST |\n            uint96(Number.unwrap(etherPrice_)) \u003c\u003c SHIFT_ETHER_PRICE |\n            uint96(Number.unwrap(markup_))\n        );\n    }\n\n    /// @notice Wraps padded uint256 value into GasData struct.\n    function wrapGasData(uint256 paddedGasData) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(paddedGasData));\n    }\n\n    /// @notice Returns the gas price, in Wei per gas unit.\n    function gasPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_GAS_PRICE));\n    }\n\n    /// @notice Returns the calldata price, in Wei per byte of content.\n    function dataPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_DATA_PRICE));\n    }\n\n    /// @notice Returns the tx fee safety buffer for message execution, in Wei.\n    function execBuffer(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_EXEC_BUFFER));\n    }\n\n    /// @notice Returns the amortized cost for attestation submission, in Wei.\n    function amortAttCost(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_AMORT_ATT_COST));\n    }\n\n    /// @notice Returns the ratio of Chain's Ether Price / Mainnet Ether Price, in BWAD math.\n    function etherPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_ETHER_PRICE));\n    }\n\n    /// @notice Returns the markup for the message execution, in BWAD math.\n    function markup(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data)));\n    }\n\n    // ════════════════════════════════════════════════ CHAIN DATA ═════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded ChainGas struct with the given fields.\n    /// @param gasData_ Chain's gas data\n    /// @param domain_  Chain's domain\n    function encodeChainGas(GasData gasData_, uint32 domain_) internal pure returns (ChainGas) {\n        // GasData type wraps uint96, so could safely be casted to uint128\n        return ChainGas.wrap(uint128(GasData.unwrap(gasData_)) \u003c\u003c SHIFT_GAS_DATA | uint128(domain_));\n    }\n\n    /// @notice Wraps padded uint256 value into ChainGas struct.\n    function wrapChainGas(uint256 paddedChainGas) internal pure returns (ChainGas) {\n        // Casting to uint128 will truncate the highest bits, which is the behavior we want\n        return ChainGas.wrap(uint128(paddedChainGas));\n    }\n\n    /// @notice Returns the chain's gas data.\n    function gasData(ChainGas data) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(ChainGas.unwrap(data) \u003e\u003e SHIFT_GAS_DATA));\n    }\n\n    /// @notice Returns the chain's domain.\n    function domain(ChainGas data) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(ChainGas.unwrap(data));\n    }\n\n    /// @notice Returns the hash for the list of ChainGas structs.\n    function snapGasHash(ChainGas[] memory snapGas) internal pure returns (bytes32 snapGasHash_) {\n        // Use assembly to calculate the hash of the array without copying it\n        // ChainGas takes a single word of storage, thus ChainGas[] is stored in the following way:\n        // 0x00: length of the array, in words\n        // 0x20: first ChainGas struct\n        // 0x40: second ChainGas struct\n        // And so on...\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Find the location where the array data starts, we add 0x20 to skip the length field\n            let loc := add(snapGas, 0x20)\n            // Load the length of the array (in words).\n            // Shifting left 5 bits is equivalent to multiplying by 32: this converts from words to bytes.\n            let len := shl(5, mload(snapGas))\n            // Calculate the hash of the array\n            snapGasHash_ := keccak256(loc, len)\n        }\n    }\n}\n\n// contracts/libs/stack/Header.sol\n\n/// Header is encoded data with \"general routing information\".\ntype Header is uint136;\n\nusing HeaderLib for Header global;\n\n/// Types of messages supported by Origin-Destination\n/// - Base: message sent by protocol user, contains tips\n/// - Manager: message sent between AgentManager contracts located on different chains, no tips\nenum MessageFlag {\n    Base,\n    Manager\n}\n\nusing HeaderLib for MessageFlag global;\n\n/// Library for formatting _the header part_ of _the messages used by Origin and Destination_.\n/// - Header represents general information for routing a Message for Origin and Destination.\n/// - Header occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n///\n/// # Header stack layout (from highest bits to lowest)\n///\n/// | Position   | Field            | Type   | Bytes | Description                             |\n/// | ---------- | ---------------- | ------ | ----- | --------------------------------------- |\n/// | (017..016] | flag             | uint8  | 1     | Flag specifying the type of message     |\n/// | (016..012] | origin           | uint32 | 4     | Domain where message originated         |\n/// | (012..008] | nonce            | uint32 | 4     | Message nonce on the origin domain      |\n/// | (008..004] | destination      | uint32 | 4     | Domain where message will be executed   |\n/// | (004..000] | optimisticPeriod | uint32 | 4     | Optimistic period that will be enforced |\nlibrary HeaderLib {\n    /// @dev Amount of bits to shift to flag field\n    uint136 private constant SHIFT_FLAG = 16 * 8;\n    /// @dev Amount of bits to shift to origin field\n    uint136 private constant SHIFT_ORIGIN = 12 * 8;\n    /// @dev Amount of bits to shift to nonce field\n    uint136 private constant SHIFT_NONCE = 8 * 8;\n    /// @dev Amount of bits to shift to destination field\n    uint136 private constant SHIFT_DESTINATION = 4 * 8;\n\n    /// @notice Returns an encoded header with provided fields\n    /// @param origin_              Domain of origin chain\n    /// @param nonce_               Message nonce on origin chain\n    /// @param destination_         Domain of destination chain\n    /// @param optimisticPeriod_    Optimistic period for message execution\n    function encodeHeader(\n        MessageFlag flag_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint32 destination_,\n        uint32 optimisticPeriod_\n    ) internal pure returns (Header) {\n        // All casts below are upcasts, so they are safe\n        // forgefmt: disable-next-item\n        return Header.wrap(\n            uint136(uint8(flag_)) \u003c\u003c SHIFT_FLAG |\n            uint136(origin_) \u003c\u003c SHIFT_ORIGIN |\n            uint136(nonce_) \u003c\u003c SHIFT_NONCE |\n            uint136(destination_) \u003c\u003c SHIFT_DESTINATION |\n            uint136(optimisticPeriod_)\n        );\n    }\n\n    /// @notice Checks that the header is a valid encoded header.\n    function isHeader(uint256 paddedHeader) internal pure returns (bool) {\n        // Check that flag is within range\n        return _flag(paddedHeader) \u003c= uint8(type(MessageFlag).max);\n    }\n\n    /// @notice Wraps the padded encoded request into a Header-typed value.\n    /// @dev The \"padded\" header is simply an encoded header casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded headers\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedHeader) internal pure returns (Header) {\n        // Check that flag is within range\n        if (!isHeader(paddedHeader)) revert FlagOutOfRange();\n        // Casting to uint136 will truncate the highest bits, which is the behavior we want\n        return Header.wrap(uint136(paddedHeader));\n    }\n\n    /// @notice Returns header's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Header header) internal pure returns (bytes32 hashedHeader) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store header in scratch space\n            mstore(0, header)\n            // Compute hash of header padded to 32 bytes\n            hashedHeader := keccak256(0, 32)\n        }\n    }\n\n    // ══════════════════════════════════════════════ HEADER SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns header's flag field\n    function flag(Header header) internal pure returns (MessageFlag) {\n        // We check that flag is within range when wrapping the header, so this cast is safe\n        return MessageFlag(_flag(Header.unwrap(header)));\n    }\n\n    /// @notice Returns header's origin field\n    function origin(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_ORIGIN);\n    }\n\n    /// @notice Returns header's nonce field\n    function nonce(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_NONCE);\n    }\n\n    /// @notice Returns header's destination field\n    function destination(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_DESTINATION);\n    }\n\n    /// @notice Returns header's optimistic seconds field\n    function optimisticPeriod(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns header's flag field without casting to MessageFlag\n    function _flag(uint256 paddedHeader) private pure returns (uint8) {\n        // Casting to uint8 will truncate the highest bits, which is the behavior we want\n        return uint8(paddedHeader \u003e\u003e SHIFT_FLAG);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n     * constructor.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall \u0026\u0026 _initialized \u003c 1) || (!AddressUpgradeable.isContract(address(this)) \u0026\u0026 _initialized == 1),\n            \"Initializable: contract is already initialized\"\n        );\n        _initialized = 1;\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: setting the version to 255 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing \u0026\u0026 _initialized \u003c version, \"Initializable: contract is already initialized\");\n        _initialized = version;\n        _initializing = true;\n        _;\n        _initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        require(_initializing, \"Initializable: contract is not initializing\");\n        _;\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized != type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint8) {\n        return _initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _initializing;\n    }\n}\n\n// contracts/interfaces/IAgentManager.sol\n\ninterface IAgentManager {\n    /**\n     * @notice Allows Inbox to open a Dispute between a Guard and a Notary, if they are both not in Dispute already.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Guard or Notary is already in Dispute.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Allows Inbox to slash an agent, if their fraud was proven.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Domain doesn't match the saved agent domain.\n     * @param domain    Domain where the Agent is active\n     * @param agent     Address of the Agent\n     * @param prover    Address that initially provided fraud proof\n     */\n    function slashAgent(uint32 domain, address agent, address prover) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest known root of the Agent Merkle Tree.\n     */\n    function agentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns the number of opened Disputes.\n     * @dev This includes the Disputes that have been resolved already.\n     */\n    function getDisputesAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns information about the dispute with the given index.\n     * @dev Will revert if dispute with given index hasn't been opened yet.\n     * @param index             Dispute index\n     * @return guard            Address of the Guard in the Dispute\n     * @return notary           Address of the Notary in the Dispute\n     * @return slashedAgent     Address of the Agent who was slashed when Dispute was resolved\n     * @return fraudProver      Address who provided fraud proof to resolve the Dispute\n     * @return reportPayload    Raw payload with report data that led to the Dispute\n     * @return reportSignature  Guard signature for the report payload\n     */\n    function getDispute(uint256 index)\n        external\n        view\n        returns (\n            address guard,\n            address notary,\n            address slashedAgent,\n            address fraudProver,\n            bytes memory reportPayload,\n            bytes memory reportSignature\n        );\n\n    /**\n     * @notice Returns the current Dispute status of a given agent. See Structures.sol for details.\n     * @dev Every returned value will be set to zero if agent was not slashed and is not in Dispute.\n     * `rival` and `disputePtr` will be set to zero if the agent was slashed without being in Dispute.\n     * @param agent         Agent address\n     * @return flag         Flag describing the current Dispute status for the agent: None/Pending/Slashed\n     * @return rival        Address of the rival agent in the Dispute\n     * @return fraudProver  Address who provided fraud proof to resolve the Dispute\n     * @return disputePtr   Index of the opened Dispute PLUS ONE. Zero if agent is not in Dispute.\n     */\n    function disputeStatus(address agent)\n        external\n        view\n        returns (DisputeFlag flag, address rival, address fraudProver, uint256 disputePtr);\n}\n\n// contracts/interfaces/IAgentSecured.sol\n\ninterface IAgentSecured {\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * between a Guard and a Notary has been opened.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * has been resolved due to one of the agents being slashed.\n     * \u003e `rivalIndex` will be ZERO, if the slashed agent was not in the Dispute.\n     * @param slashedIndex  Index of the slashed agent in the Agent Merkle Tree\n     * @param rivalIndex    Index of the their Dispute Rival in the Agent Merkle Tree\n     */\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the address of the local AgentManager contract, which is treated as\n     * the \"source of truth\" for agent statuses.\n     */\n    function agentManager() external view returns (address);\n\n    /**\n     * @notice Returns the address of the local Inbox contract, which is treated as\n     * the \"source of truth\" for agent-signed statements.\n     * @dev Inbox passes verified agent statements to `IAgentSecured` contract.\n     */\n    function inbox() external view returns (address);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns (flag, openedAt, resolvedAt) that describes the latest status of\n     * the latest dispute for an agent with a given index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param agentIndex    Agent index in the Agent Merkle Tree\n     * @return              Latest dispute status for the given agent: (flag, openedAt, resolvedAt)\n     */\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory);\n}\n\n// contracts/libs/memory/ByteString.sol\n\n/// @dev CallData is a memory view over the payload to be used for an external call, i.e.\n/// recipient.call(callData). Its length is always (4 + 32 * N) bytes:\n/// - First 4 bytes represent the function selector.\n/// - 32 * N bytes represent N words that function arguments occupy.\ntype CallData is uint256;\n\n/// @dev Attach library functions to CallData\nusing ByteString for CallData global;\n\n/// @dev Signature is a memory view over a \"65 bytes\" array representing a ECDSA signature.\ntype Signature is uint256;\n\n/// @dev Attach library functions to Signature\nusing ByteString for Signature global;\n\nlibrary ByteString {\n    using MemViewLib for bytes;\n\n    /**\n     * @dev non-compact ECDSA signatures are enforced as of OZ 4.7.3\n     *\n     *      Signature payload memory layout\n     * [000 .. 032) r   bytes32 32 bytes\n     * [032 .. 064) s   bytes32 32 bytes\n     * [064 .. 065) v   uint8    1 byte\n     */\n    uint256 internal constant SIGNATURE_LENGTH = 65;\n    uint256 private constant OFFSET_R = 0;\n    uint256 private constant OFFSET_S = 32;\n    uint256 private constant OFFSET_V = 64;\n\n    /**\n     * @dev Calldata memory layout\n     * [000 .. 004) selector    bytes4  4 bytes\n     *      Optional: N function arguments\n     * [004 .. 036) arg1        bytes32 32 bytes\n     *      ..\n     * [AAA .. END) argN        bytes32 32 bytes\n     */\n    uint256 internal constant SELECTOR_LENGTH = 4;\n    uint256 private constant OFFSET_SELECTOR = 0;\n    uint256 private constant OFFSET_ARGUMENTS = SELECTOR_LENGTH;\n\n    // ═════════════════════════════════════════════════ SIGNATURE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the signature payload from the given values.\n     * @dev Using ByteString.formatSignature({r: r, s: s, v: v}) will make sure\n     * that params are given in the right order.\n     */\n    function formatSignature(bytes32 r, bytes32 s, uint8 v) internal pure returns (bytes memory) {\n        return abi.encodePacked(r, s, v);\n    }\n\n    /**\n     * @notice Returns a Signature view over for the given payload.\n     * @dev Will revert if the payload is not a signature.\n     */\n    function castToSignature(bytes memory payload) internal pure returns (Signature) {\n        return castToSignature(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Signature view.\n     * @dev Will revert if the memory view is not over a signature.\n     */\n    function castToSignature(MemView memView) internal pure returns (Signature) {\n        if (!isSignature(memView)) revert UnformattedSignature();\n        return Signature.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a signature\n     */\n    function isSignature(MemView memView) internal pure returns (bool) {\n        return memView.len() == SIGNATURE_LENGTH;\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Signature signature) internal pure returns (MemView) {\n        return MemView.wrap(Signature.unwrap(signature));\n    }\n\n    // ═════════════════════════════════════════════ SIGNATURE SLICING ═════════════════════════════════════════════════\n\n    /// @notice Unpacks signature payload into (r, s, v) parameters.\n    /// @dev Make sure to verify signature length with isSignature() beforehand.\n    function toRSV(Signature signature) internal pure returns (bytes32 r, bytes32 s, uint8 v) {\n        // Get the underlying memory view\n        MemView memView = unwrap(signature);\n        r = memView.index({index_: OFFSET_R, bytes_: 32});\n        s = memView.index({index_: OFFSET_S, bytes_: 32});\n        // Can be safely casted to uint8, since we index a single byte\n        v = uint8(memView.indexUint({index_: OFFSET_V, bytes_: 1}));\n    }\n\n    // ═════════════════════════════════════════════════ CALLDATA ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the calldata with the modified arguments:\n     * the existing arguments are prepended with the arguments from the prefix.\n     * @dev Given:\n     *  - `calldata = abi.encodeWithSelector(foo.selector, d, e);`\n     *  - `prefix = abi.encode(a, b, c);`\n     *  - `a`, `b`, `c` are arguments of static type (i.e. not dynamically sized ones)\n     *      Then:\n     *  - Function will return abi.encodeWithSelector(foo.selector, a, c, c, d, e)\n     *  - Returned calldata will trigger `foo(a, b, c, d, e)` when used for a contract call.\n     * Note: for clarification as to what types are considered static, see\n     * https://docs.soliditylang.org/en/latest/abi-spec.html#formal-specification-of-the-encoding\n     * @param callData  Calldata that needs to be modified\n     * @param prefix    ABI-encoded arguments to use as the first arguments in the new calldata\n     * @return Modified calldata having prefix as the first arguments.\n     */\n    function addPrefix(CallData callData, bytes memory prefix) internal view returns (bytes memory) {\n        // Prefix should occupy a whole amount of words in memory\n        if (!_fullWords(prefix.length)) revert UnformattedCallDataPrefix();\n        MemView[] memory views = new MemView[](3);\n        // Use payload's function selector\n        views[0] = abi.encodePacked(callData.callSelector()).ref();\n        // Use prefix as the first arguments\n        views[1] = prefix.ref();\n        // Use payload's remaining arguments\n        views[2] = callData.arguments();\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a CallData view over for the given payload.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(bytes memory payload) internal pure returns (CallData) {\n        return castToCallData(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a CallData view.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(MemView memView) internal pure returns (CallData) {\n        if (!isCallData(memView)) revert UnformattedCallData();\n        return CallData.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a valid calldata, i.e.\n     * a function selector, followed by arbitrary amount of arguments.\n     */\n    function isCallData(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Calldata should at least have a function selector\n        if (length \u003c SELECTOR_LENGTH) return false;\n        // The remainder of the calldata should be exactly N memory words (N \u003e= 0)\n        return _fullWords(length - SELECTOR_LENGTH);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(CallData callData) internal pure returns (MemView) {\n        return MemView.wrap(CallData.unwrap(callData));\n    }\n\n    /// @notice Returns callData's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(CallData callData) internal pure returns (bytes32) {\n        return callData.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ CALLDATA SLICING ══════════════════════════════════════════════════\n\n    /**\n     * @notice Returns amount of memory words (32 byte chunks) the function arguments\n     * occupy in the calldata.\n     * @dev This might differ from amount of arguments supplied, if any of the arguments\n     * occupies more than one memory slot. It is true, however, that argument part of the payload\n     * occupies exactly N words, even for dynamic types like `bytes`\n     */\n    function argumentWords(CallData callData) internal pure returns (uint256) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        // Equivalent of (length - SELECTOR_LENGTH) / 32\n        return (memView.len() - SELECTOR_LENGTH) \u003e\u003e 5;\n    }\n\n    /// @notice Returns selector for the provided calldata.\n    function callSelector(CallData callData) internal pure returns (bytes4) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return bytes4(memView.index({index_: OFFSET_SELECTOR, bytes_: SELECTOR_LENGTH}));\n    }\n\n    /// @notice Returns abi encoded arguments for the provided calldata.\n    function arguments(CallData callData) internal pure returns (MemView) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return memView.sliceFrom({index_: OFFSET_ARGUMENTS});\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if length is full amount of memory words (32 bytes).\n    function _fullWords(uint256 length) internal pure returns (bool) {\n        // The equivalent of length % 32 == 0\n        return length \u0026 31 == 0;\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n    function __Context_init() internal onlyInitializing {\n    }\n\n    function __Context_init_unchained() internal onlyInitializing {\n    }\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[50] private __gap;\n}\n\n// contracts/libs/merkle/MerkleTree.sol\n\n/// `BaseTree` is a struct representing incremental merkle tree.\n/// - Contains only the current branch.\n/// - The number of inserted leaves is stored externally, and is later supplied for tree operations.\n/// - Has a fixed height of `ORIGIN_TREE_HEIGHT`.\n/// - Can store up to `2 ** ORIGIN_TREE_HEIGHT - 1` leaves.\n/// \u003e Note: the hash function for the tree `H(x, y)` is defined as:\n/// \u003e - `H(0,0) = 0`\n/// \u003e - `H(x,y) = keccak256(x, y), when (x != 0 || y != 0)`\n/// ## Invariant for leafs\n/// - The leftmost empty leaf has `index == count`, where `count` is the amount of the inserted leafs so far.\n/// - Value for any empty leaf or node is bytes32(0).\n/// ## Invariant for current branch\n/// `branch[i]` is always the value of a node on the i-th level.\n/// Levels are numbered from leafs to root: `0 .. ORIGIN_TREE_HEIGHT`.\n/// `branch[i]` stores the value for the node, such that:\n//  - The node is a \"left child\" (e.g. has an even index).\n/// - The node must have two non-empty children.\n/// - Out of all level's \"left child\" nodes with \"non-empty children\",\n/// the one with the biggest index (the rightmost one) is stored as `branch[i]`.\n/// \u003e __`branch` could be used to form a proof of inclusion for the first empty leaf (`index == count`).__\n/// _Here is how:_\n/// - Let's walk along the path from the \"first empty leaf\" to the root.\n/// - i-th bit of the \"first empty leaf\" index (which is equal to `count`) determines if the path's node\n/// for this i-th level is a \"left child\" or a \"right child\".\n/// - i-th bit in `count` is 0 → we are the left child on this level → sibling is the right child\n/// that does not exist yet → `proof[i] = bytes32(0)`.\n/// - i-th bit in `count` is 1 → we are the right child on this level → sibling is the left child\n/// sibling is the rightmost \"left child\" node on the level → `proof[i] = branch[i]`.\n/// \u003e Therefore `proof[i] = (count \u0026 (1 \u003c\u003c i)) == 0 ? bytes32(0) : branch[i])`\nstruct BaseTree {\n    bytes32[ORIGIN_TREE_HEIGHT] branch;\n}\n\nusing MerkleTree for BaseTree global;\n\n/// `HistoricalTree` is an incremental merkle tree keeping track of its historical merkle roots.\n/// \u003e - `roots[N]` is the root of the tree after `N` leafs were inserted\n/// \u003e - `roots[0] == bytes32(0)`\n/// @param tree     Incremental merkle tree\n/// @param roots    Historical merkle roots of the tree\nstruct HistoricalTree {\n    BaseTree tree;\n    bytes32[] roots;\n}\n\nusing MerkleTree for HistoricalTree global;\n\n/// `DynamicTree` is a struct representing a Merkle Tree with `2**AGENT_TREE_HEIGHT` leaves.\n/// - A single operation is available: update value for leaf with an arbitrary index (which might be a non-empty leaf).\n/// - This is done by requesting the proof of inclusion for the old value, which is used to both\n/// verify the old value, and calculate the new root.\n/// \u003e Based on Original idea from [ER forum post](https://ethresear.ch/t/efficient-on-chain-dynamic-merkle-tree/11054).\nstruct DynamicTree {\n    bytes32 root;\n}\n\nusing MerkleTree for DynamicTree global;\n\n/// MerkleTree is work based on Nomad's Merkle.sol, which is used under MIT OR Apache-2.0\n/// [link](https://github.com/nomad-xyz/monorepo/blob/main/packages/contracts-core/contracts/libs/Merkle.sol).\n/// With the following changes:\n/// - Adapted for Solidity 0.8.x.\n/// - Amount of tree leaves stored externally.\n/// - Added thorough documentation.\n/// - `H(0,0) = 0` optimization from [ER forum post](https://ethresear.ch/t/optimizing-sparse-merkle-trees/3751/6).\n/// \u003e Nomad's Merkle.sol is work based on eth2 deposit contract, which is used under CC0-1.0\n///[link](https://github.com/ethereum/deposit_contract/blob/dev/deposit_contract/contracts/validator_registration.v.py).\n/// With the following changes:\n/// \u003e - Implemented in Solidity 0.7.6 (eth2 deposit contract implemented in Vyper).\n/// \u003e - `H() = keccak256()` is used as the hashing function instead of `sha256()`.\nlibrary MerkleTree {\n    /// @dev For root calculation we need at least one empty leaf, thus the minus one in the formula.\n    uint256 internal constant MAX_LEAVES = 2 ** ORIGIN_TREE_HEIGHT - 1;\n\n    // ═════════════════════════════════════════════════ BASE TREE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Inserts `node` into merkle tree\n     * @dev Reverts if tree is full\n     * @param newCount  Amount of inserted leaves in the tree after the insertion (i.e. current + 1)\n     * @param node      Element to insert into tree\n     */\n    function insertBase(BaseTree storage tree, uint256 newCount, bytes32 node) internal {\n        if (newCount \u003e MAX_LEAVES) revert MerkleTreeFull();\n        // We go up the tree following the branch from the empty leaf AFTER the just inserted one.\n        // We stop when we find the first \"right child\" node.\n        // Its sibling is now the rightmost \"left child\" node that has two non-empty children.\n        // Therefore we need to update `tree.branch` value on this level.\n        // One could see that `tree.branch` value on lower and higher levels remain unchanged.\n\n        // Loop invariant: `node` is the current level's value for the branch from JUST INSERTED leaf\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            if ((newCount \u0026 1) == 1) {\n                // Found the first \"right child\" node on the branch from EMPTY leaf\n                // `node` is the value for node on branch from JUST INSERTED leaf\n                // Which in this case is the \"left child\".\n                // We update tree.branch and exit\n                tree.branch[i] = node;\n                return;\n            }\n            // On the branch from EMPTY leaf this is still a \"left child\".\n            // Meaning on branch from JUST INSERTED leaf, `node` is a right child.\n            // We compute value for `node` parent using `tree.branch` invariant:\n            // This is the rightmost \"left child\" node, which would be sibling of `node`.\n            node = MerkleMath.getParent(tree.branch[i], node);\n            // Get the parent index, and go to the next tree level\n            newCount \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n        // As the loop should always end prematurely with the `return` statement,\n        // this code should be unreachable. We assert `false` just to be safe.\n        assert(false);\n    }\n\n    /**\n     * @notice Calculates and returns current root of the merkle tree.\n     * @param count     Current amount of inserted leaves in the tree\n     * @return current  Calculated root of `tree`\n     */\n    function rootBase(BaseTree storage tree, uint256 count) internal view returns (bytes32 current) {\n        // To calculate the root we follow the branch of first EMPTY leaf (index == count)\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            // Check if we are the left or the right child on the current level\n            if ((count \u0026 1) == 1) {\n                // We are the right child. Our sibling is the \"rightmost\" \"left-child\" node\n                // that has two non-empty children → sibling is `tree.branch[i]`\n                current = MerkleMath.getParent(tree.branch[i], current);\n            } else {\n                // We are the left child. Our sibling does not exist yet → sibling is EMPTY\n                current = MerkleMath.getParent(current, bytes32(0));\n            }\n            // Get the parent index, and go to the next tree level\n            count \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    // ══════════════════════════════════════════════ HISTORICAL TREE ══════════════════════════════════════════════════\n\n    /// @notice Initializes the historical roots for the tree by inserting an empty root.\n    // solhint-disable-next-line ordering\n    function initializeRoots(HistoricalTree storage tree) internal returns (bytes32 savedRoot) {\n        // This should only be called once, when the contract is initialized\n        assert(tree.roots.length == 0);\n        // Save root for empty merkle tree: bytes32(0)\n        tree.roots.push(savedRoot);\n    }\n\n    /// @notice Inserts a new leaf into the merkle tree.\n    /// @dev Reverts if tree is full.\n    /// @param node         Element to insert into tree\n    /// @return newRoot     Merkle root after the leaf was inserted\n    function insert(HistoricalTree storage tree, bytes32 node) internal returns (bytes32 newRoot) {\n        // Tree count after the new leaf will be inserted (we store roots[0] as root of empty tree)\n        uint256 newCount = tree.roots.length;\n        tree.tree.insertBase(newCount, node);\n        // Save the new root\n        newRoot = tree.tree.rootBase(newCount);\n        tree.roots.push(newRoot);\n    }\n\n    /// @notice Returns the historical root of the merkle tree.\n    /// @dev Reverts if not enough leafs have been inserted.\n    /// @param count            Amount of leafs in the tree at some point of time\n    /// @return historicalRoot  Merkle root after `count` leafs were inserted\n    function root(HistoricalTree storage tree, uint256 count) internal view returns (bytes32 historicalRoot) {\n        if (count \u003e= tree.roots.length) revert NotEnoughLeafs();\n        return tree.roots[count];\n    }\n\n    // ═══════════════════════════════════════════════ DYNAMIC TREE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Updates the value for the leaf with the given index in the Dynamic Merkle Tree.\n     * @dev Will revert if incorrect proof of inclusion for old value is supplied.\n     * @param tree          Dynamic merkle tree\n     * @param index         Index of the leaf to update\n     * @param oldValue      Previous value of the leaf\n     * @param branch        Proof of inclusion of previous value into the tree\n     * @param newValue      New leaf value to assign\n     * @return newRoot      New value for the Merkle Root after the leaf is updated\n     */\n    function update(\n        DynamicTree storage tree,\n        uint256 index,\n        bytes32 oldValue,\n        bytes32[] memory branch,\n        bytes32 newValue\n    ) internal returns (bytes32 newRoot) {\n        // Check that the old value + proof result in a correct root\n        if (MerkleMath.proofRoot(index, oldValue, branch, AGENT_TREE_HEIGHT) != tree.root) {\n            revert LeafNotProven();\n        }\n        // New root is new value + the same proof (values for sibling nodes are not updated)\n        newRoot = MerkleMath.proofRoot(index, newValue, branch, AGENT_TREE_HEIGHT);\n        // Write the new root\n        tree.root = newRoot;\n    }\n}\n\n// contracts/libs/stack/Tips.sol\n\n/// Tips is encoded data with \"tips paid for sending a base message\".\n/// Note: even though uint256 is also an underlying type for MemView, Tips is stored ON STACK.\ntype Tips is uint256;\n\nusing TipsLib for Tips global;\n\n/// # Tips\n/// Library for formatting _the tips part_ of _the base messages_.\n///\n/// ## How the tips are awarded\n/// Tips are paid for sending a base message, and are split across all the agents that\n/// made the message execution on destination chain possible.\n/// ### Summit tips\n/// Split between:\n///     - Guard posting a snapshot with state ST_G for the origin chain.\n///     - Notary posting a snapshot SN_N using ST_G. This creates attestation A.\n///     - Notary posting a message receipt after it is executed on destination chain.\n/// ### Attestation tips\n/// Paid to:\n///     - Notary posting attestation A to destination chain.\n/// ### Execution tips\n/// Paid to:\n///     - First executor performing a valid execution attempt (correct proofs, optimistic period over),\n///      using attestation A to prove message inclusion on origin chain, whether the recipient reverted or not.\n/// ### Delivery tips.\n/// Paid to:\n///     - Executor who successfully executed the message on destination chain.\n///\n/// ## Tips encoding\n/// - Tips occupy a single storage word, and thus are stored on stack instead of being stored in memory.\n/// - The actual tip values should be determined by multiplying stored values by divided by TIPS_MULTIPLIER=2**32.\n/// - Tips are packed into a single word of storage, while allowing real values up to ~8*10**28 for every tip category.\n/// \u003e The only downside is that the \"real tip values\" are now multiplies of ~4*10**9, which should be fine even for\n/// the chains with the most expensive gas currency.\n/// # Tips stack layout (from highest bits to lowest)\n///\n/// | Position   | Field          | Type   | Bytes | Description                                                |\n/// | ---------- | -------------- | ------ | ----- | ---------------------------------------------------------- |\n/// | (032..024] | summitTip      | uint64 | 8     | Tip for agents interacting with Summit contract            |\n/// | (024..016] | attestationTip | uint64 | 8     | Tip for Notary posting attestation to Destination contract |\n/// | (016..008] | executionTip   | uint64 | 8     | Tip for valid execution attempt on destination chain       |\n/// | (008..000] | deliveryTip    | uint64 | 8     | Tip for successful message delivery on destination chain   |\n\nlibrary TipsLib {\n    using SafeCast for uint256;\n\n    /// @dev Amount of bits to shift to summitTip field\n    uint256 private constant SHIFT_SUMMIT_TIP = 24 * 8;\n    /// @dev Amount of bits to shift to attestationTip field\n    uint256 private constant SHIFT_ATTESTATION_TIP = 16 * 8;\n    /// @dev Amount of bits to shift to executionTip field\n    uint256 private constant SHIFT_EXECUTION_TIP = 8 * 8;\n\n    // ═══════════════════════════════════════════════════ TIPS ════════════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips with the given fields\n    /// @param summitTip_        Tip for agents interacting with Summit contract, divided by TIPS_MULTIPLIER\n    /// @param attestationTip_   Tip for Notary posting attestation to Destination contract, divided by TIPS_MULTIPLIER\n    /// @param executionTip_     Tip for valid execution attempt on destination chain, divided by TIPS_MULTIPLIER\n    /// @param deliveryTip_      Tip for successful message delivery on destination chain, divided by TIPS_MULTIPLIER\n    function encodeTips(uint64 summitTip_, uint64 attestationTip_, uint64 executionTip_, uint64 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // forgefmt: disable-next-item\n        return Tips.wrap(\n            uint256(summitTip_) \u003c\u003c SHIFT_SUMMIT_TIP |\n            uint256(attestationTip_) \u003c\u003c SHIFT_ATTESTATION_TIP |\n            uint256(executionTip_) \u003c\u003c SHIFT_EXECUTION_TIP |\n            uint256(deliveryTip_)\n        );\n    }\n\n    /// @notice Convenience function to encode tips with uint256 values.\n    function encodeTips256(uint256 summitTip_, uint256 attestationTip_, uint256 executionTip_, uint256 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // In practice, the tips amounts are not supposed to be higher than 2**96, and with 32 bits of granularity\n        // using uint64 is enough to store the values. However, we still check for overflow just in case.\n        // TODO: consider using Number type to store the tips values.\n        return encodeTips({\n            summitTip_: (summitTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            attestationTip_: (attestationTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            executionTip_: (executionTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            deliveryTip_: (deliveryTip_ \u003e\u003e TIPS_GRANULARITY).toUint64()\n        });\n    }\n\n    /// @notice Wraps the padded encoded tips into a Tips-typed value.\n    /// @dev There is no actual padding here, as the underlying type is already uint256,\n    /// but we include this function for consistency and to be future-proof, if tips will eventually use anything\n    /// smaller than uint256.\n    function wrapPadded(uint256 paddedTips) internal pure returns (Tips) {\n        return Tips.wrap(paddedTips);\n    }\n\n    /**\n     * @notice Returns a formatted Tips payload specifying empty tips.\n     * @return Formatted tips\n     */\n    function emptyTips() internal pure returns (Tips) {\n        return Tips.wrap(0);\n    }\n\n    /// @notice Returns tips's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Tips tips) internal pure returns (bytes32 hashedTips) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store tips in scratch space\n            mstore(0, tips)\n            // Compute hash of tips padded to 32 bytes\n            hashedTips := keccak256(0, 32)\n        }\n    }\n\n    // ═══════════════════════════════════════════════ TIPS SLICING ════════════════════════════════════════════════════\n\n    /// @notice Returns summitTip field\n    function summitTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_SUMMIT_TIP);\n    }\n\n    /// @notice Returns attestationTip field\n    function attestationTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_ATTESTATION_TIP);\n    }\n\n    /// @notice Returns executionTip field\n    function executionTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_EXECUTION_TIP);\n    }\n\n    /// @notice Returns deliveryTip field\n    function deliveryTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips));\n    }\n\n    // ════════════════════════════════════════════════ TIPS VALUE ═════════════════════════════════════════════════════\n\n    /// @notice Returns total value of the tips payload.\n    /// This is the sum of the encoded values, scaled up by TIPS_MULTIPLIER\n    function value(Tips tips) internal pure returns (uint256 value_) {\n        value_ = uint256(tips.summitTip()) + tips.attestationTip() + tips.executionTip() + tips.deliveryTip();\n        value_ \u003c\u003c= TIPS_GRANULARITY;\n    }\n\n    /// @notice Increases the delivery tip to match the new value.\n    function matchValue(Tips tips, uint256 newValue) internal pure returns (Tips newTips) {\n        uint256 oldValue = tips.value();\n        if (newValue \u003c oldValue) revert TipsValueTooLow();\n        // We want to increase the delivery tip, while keeping the other tips the same\n        unchecked {\n            uint256 delta = (newValue - oldValue) \u003e\u003e TIPS_GRANULARITY;\n            // `delta` fits into uint224, as TIPS_GRANULARITY is 32, so this never overflows uint256.\n            // In practice, this will never overflow uint64 as well, but we still check it just in case.\n            if (delta + tips.deliveryTip() \u003e type(uint64).max) revert TipsOverflow();\n            // Delivery tips occupy lowest 8 bytes, so we can just add delta to the tips value\n            // to effectively increase the delivery tip (knowing that delta fits into uint64).\n            newTips = Tips.wrap(Tips.unwrap(tips) + delta);\n        }\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    function __Ownable_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable_init_unchained() internal onlyInitializing {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n    function __Ownable2Step_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable2Step_init_unchained() internal onlyInitializing {\n    }\n    address private _pendingOwner;\n\n    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Returns the address of the pending owner.\n     */\n    function pendingOwner() public view virtual returns (address) {\n        return _pendingOwner;\n    }\n\n    /**\n     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual override onlyOwner {\n        _pendingOwner = newOwner;\n        emit OwnershipTransferStarted(owner(), newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual override {\n        delete _pendingOwner;\n        super._transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev The new owner accepts the ownership transfer.\n     */\n    function acceptOwnership() public virtual {\n        address sender = _msgSender();\n        require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n        _transferOwnership(sender);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// contracts/libs/memory/State.sol\n\n/// State is a memory view over a formatted state payload.\ntype State is uint256;\n\nusing StateLib for State global;\n\n/// # State\n/// State structure represents the state of Origin contract at some point of time.\n/// - State is structured in a way to track the updates of the Origin Merkle Tree.\n/// - State includes root of the Origin Merkle Tree, origin domain and some additional metadata.\n/// ## Origin Merkle Tree\n/// Hash of every sent message is inserted in the Origin Merkle Tree, which changes\n/// the value of Origin Merkle Root (which is the root for the mentioned tree).\n/// - Origin has a single Merkle Tree for all messages, regardless of their destination domain.\n/// - This leads to Origin state being updated if and only if a message was sent in a block.\n/// - Origin contract is a \"source of truth\" for states: a state is considered \"valid\" in its Origin,\n/// if it matches the state of the Origin contract after the N-th (nonce) message was sent.\n///\n/// # Memory layout of State fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                    |\n/// | ---------- | ----------- | ------- | ----- | ------------------------------ |\n/// | [000..032) | root        | bytes32 | 32    | Root of the Origin Merkle Tree |\n/// | [032..036) | origin      | uint32  | 4     | Domain where Origin is located |\n/// | [036..040) | nonce       | uint32  | 4     | Amount of sent messages        |\n/// | [040..045) | blockNumber | uint40  | 5     | Block of last sent message     |\n/// | [045..050) | timestamp   | uint40  | 5     | Time of last sent message      |\n/// | [050..062) | gasData     | uint96  | 12    | Gas data for the chain         |\n///\n/// @dev State could be used to form a Snapshot to be signed by a Guard or a Notary.\nlibrary StateLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_ROOT = 0;\n    uint256 private constant OFFSET_ORIGIN = 32;\n    uint256 private constant OFFSET_NONCE = 36;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 40;\n    uint256 private constant OFFSET_TIMESTAMP = 45;\n    uint256 private constant OFFSET_GAS_DATA = 50;\n\n    // ═══════════════════════════════════════════════════ STATE ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted State payload with provided fields\n     * @param root_         New merkle root\n     * @param origin_       Domain of Origin's chain\n     * @param nonce_        Nonce of the merkle root\n     * @param blockNumber_  Block number when root was saved in Origin\n     * @param timestamp_    Block timestamp when root was saved in Origin\n     * @param gasData_      Gas data for the chain\n     * @return Formatted state\n     */\n    function formatState(\n        bytes32 root_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_,\n        GasData gasData_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(root_, origin_, nonce_, blockNumber_, timestamp_, gasData_);\n    }\n\n    /**\n     * @notice Returns a State view over the given payload.\n     * @dev Will revert if the payload is not a state.\n     */\n    function castToState(bytes memory payload) internal pure returns (State) {\n        return castToState(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a State view.\n     * @dev Will revert if the memory view is not over a state.\n     */\n    function castToState(MemView memView) internal pure returns (State) {\n        if (!isState(memView)) revert UnformattedState();\n        return State.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted State.\n    function isState(MemView memView) internal pure returns (bool) {\n        return memView.len() == STATE_LENGTH;\n    }\n\n    /// @notice Returns the hash of a State, that could be later signed by a Guard to signal\n    /// that the state is invalid.\n    function hashInvalid(State state) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(stateInvalidSalt, keccak(state))\n        return state.unwrap().keccakSalted(STATE_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(State state) internal pure returns (MemView) {\n        return MemView.wrap(State.unwrap(state));\n    }\n\n    /// @notice Compares two State structures.\n    function equals(State a, State b) internal pure returns (bool) {\n        // Length of a State payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═══════════════════════════════════════════════ STATE HASHING ═══════════════════════════════════════════════════\n\n    /// @notice Returns the hash of the State.\n    /// @dev We are using the Merkle Root of a tree with two leafs (see below) as state hash.\n    function leaf(State state) internal pure returns (bytes32) {\n        (bytes32 leftLeaf_, bytes32 rightLeaf_) = state.subLeafs();\n        // Final hash is the parent of these leafs\n        return keccak256(bytes.concat(leftLeaf_, rightLeaf_));\n    }\n\n    /// @notice Returns \"sub-leafs\" of the State. Hash of these \"sub leafs\" is going to be used\n    /// as a \"state leaf\" in the \"Snapshot Merkle Tree\".\n    /// This enables proving that leftLeaf = (root, origin) was a part of the \"Snapshot Merkle Tree\",\n    /// by combining `rightLeaf` with the remainder of the \"Snapshot Merkle Proof\".\n    function subLeafs(State state) internal pure returns (bytes32 leftLeaf_, bytes32 rightLeaf_) {\n        MemView memView = state.unwrap();\n        // Left leaf is (root, origin)\n        leftLeaf_ = memView.prefix({len_: OFFSET_NONCE}).keccak();\n        // Right leaf is (metadata), or (nonce, blockNumber, timestamp)\n        rightLeaf_ = memView.sliceFrom({index_: OFFSET_NONCE}).keccak();\n    }\n\n    /// @notice Returns the left \"sub-leaf\" of the State.\n    function leftLeaf(bytes32 root_, uint32 origin_) internal pure returns (bytes32) {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(root_, origin_));\n    }\n\n    /// @notice Returns the right \"sub-leaf\" of the State.\n    function rightLeaf(uint32 nonce_, uint40 blockNumber_, uint40 timestamp_, GasData gasData_)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(nonce_, blockNumber_, timestamp_, gasData_));\n    }\n\n    // ═══════════════════════════════════════════════ STATE SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns a historical Merkle root from the Origin contract.\n    function root(State state) internal pure returns (bytes32) {\n        return state.unwrap().index({index_: OFFSET_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns domain of chain where the Origin contract is deployed.\n    function origin(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns nonce of Origin contract at the time, when `root` was the Merkle root.\n    function nonce(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when `root` was saved in Origin.\n    function blockNumber(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when `root` was saved in Origin.\n    /// @dev This is the timestamp according to the origin chain.\n    function timestamp(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n\n    /// @notice Returns gas data for the chain.\n    function gasData(State state) internal pure returns (GasData) {\n        return GasDataLib.wrapGasData(state.unwrap().indexUint({index_: OFFSET_GAS_DATA, bytes_: GAS_DATA_LENGTH}));\n    }\n}\n\n// contracts/libs/memory/BaseMessage.sol\n\n/// BaseMessage is a memory view over the base message supported by Origin-Destination\ntype BaseMessage is uint256;\n\nusing BaseMessageLib for BaseMessage global;\n\n/// BaseMessage structure represents a base message sent via the Origin-Destination contracts.\n/// - It only contains data relevant to the base message, the rest of data is encoded in the message header.\n/// - `sender` and `recipient` for EVM chains are EVM addresses casted to bytes32, while preserving left-alignment.\n/// - `tips` and `request` parameters are specified by a message sender\n/// \u003e Origin will calculate minimum tips for given request and content length, and will reject messages with tips\n/// lower than that.\n///\n/// # Memory layout of BaseMessage fields\n///\n/// | Position   | Field     | Type    | Bytes | Description                            |\n/// | ---------- | --------- | ------- | ----- | -------------------------------------- |\n/// | [000..032) | tips      | uint256 | 32    | Encoded tips paid on origin chain      |\n/// | [032..064) | sender    | bytes32 | 32    | Sender address on origin chain         |\n/// | [064..096) | recipient | bytes32 | 32    | Recipient address on destination chain |\n/// | [096..116) | request   | uint160 | 20    | Encoded request for message execution  |\n/// | [104..AAA) | content   | bytes   | ??    | Content to be passed to recipient      |\nlibrary BaseMessageLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_TIPS = 0;\n    uint256 private constant OFFSET_SENDER = 32;\n    uint256 private constant OFFSET_RECIPIENT = 64;\n    uint256 private constant OFFSET_REQUEST = OFFSET_RECIPIENT + TIPS_LENGTH;\n    uint256 private constant OFFSET_CONTENT = OFFSET_REQUEST + REQUEST_LENGTH;\n\n    // ═══════════════════════════════════════════════ BASE MESSAGE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted BaseMessage payload with provided fields.\n     * @param tips_         Encoded tips information\n     * @param sender_       Sender address on origin chain\n     * @param recipient_    Recipient address on destination chain\n     * @param request_      Encoded request for message execution\n     * @param content_      Raw content to be passed to recipient on destination chain\n     * @return Formatted base message\n     */\n    function formatBaseMessage(Tips tips_, bytes32 sender_, bytes32 recipient_, Request request_, bytes memory content_)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return abi.encodePacked(tips_, sender_, recipient_, request_, content_);\n    }\n\n    /**\n     * @notice Returns a BaseMessage view over the given payload.\n     * @dev Will revert if the payload is not a base message.\n     */\n    function castToBaseMessage(bytes memory payload) internal pure returns (BaseMessage) {\n        return castToBaseMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a BaseMessage view.\n     * @dev Will revert if the memory view is not over a base message payload.\n     */\n    function castToBaseMessage(MemView memView) internal pure returns (BaseMessage) {\n        if (!isBaseMessage(memView)) revert UnformattedBaseMessage();\n        return BaseMessage.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted BaseMessage.\n    function isBaseMessage(MemView memView) internal pure returns (bool) {\n        // Check if sender, recipient, tips fields exist\n        return (memView.len() \u003e= OFFSET_CONTENT);\n        // Content could be empty, so we don't check that\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(BaseMessage baseMessage) internal pure returns (MemView) {\n        return MemView.wrap(BaseMessage.unwrap(baseMessage));\n    }\n\n    /// @notice Returns baseMessage's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        // We hash \"tips\" and \"everything but tips\" to make tips proofs easier to verify\n        return MerkleMath.getParent(baseMessage.tips().leaf(), baseMessage.bodyLeaf());\n    }\n\n    /// @notice Returns hash for the \"everything but tips\" part of the base message.\n    function bodyLeaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_SENDER}).keccak();\n    }\n\n    // ═══════════════════════════════════════════ BASE MESSAGE SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips paid on origin chain.\n    function tips(BaseMessage baseMessage) internal pure returns (Tips) {\n        return TipsLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_TIPS, bytes_: TIPS_LENGTH})));\n    }\n\n    /// @notice Returns sender address on origin chain.\n    function sender(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_SENDER, bytes_: 32});\n    }\n\n    /// @notice Returns recipient address on destination chain.\n    function recipient(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_RECIPIENT, bytes_: 32});\n    }\n\n    /// @notice Returns an encoded request for message execution on destination chain.\n    function request(BaseMessage baseMessage) internal pure returns (Request) {\n        return RequestLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_REQUEST, bytes_: REQUEST_LENGTH})));\n    }\n\n    /// @notice Returns an untyped memory view over the content to be passed to recipient.\n    function content(BaseMessage baseMessage) internal pure returns (MemView) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_CONTENT});\n    }\n}\n\n// contracts/base/MessagingBase.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for all messaging contracts.\n * - Provides context on the local chain's domain.\n * - Provides ownership functionality.\n * - Will be providing pausing functionality when it is implemented.\n */\nabstract contract MessagingBase is MultiCallable, Versioned, Ownable2StepUpgradeable {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @notice Domain of the local chain, set once upon contract creation\n    uint32 public immutable localDomain;\n    // @notice Domain of the Synapse chain, set once upon contract creation\n    uint32 public immutable synapseDomain;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev gap for upgrade safety\n    uint256[50] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    constructor(string memory version_, uint32 synapseDomain_) Versioned(version_) {\n        localDomain = ChainContext.chainId();\n        synapseDomain = synapseDomain_;\n    }\n\n    // TODO: Implement pausing\n\n    /**\n     * @dev Should be impossible to renounce ownership;\n     * we override OpenZeppelin OwnableUpgradeable's\n     * implementation of renounceOwnership to make it a no-op\n     */\n    function renounceOwnership() public override onlyOwner {} //solhint-disable-line no-empty-blocks\n}\n\n// contracts/libs/memory/Message.sol\n\n/// Message is a memory over over a formatted message payload.\ntype Message is uint256;\n\nusing MessageLib for Message global;\n\n/// Library for formatting the various messages supported by Origin and Destination.\n///\n/// # Message memory layout\n///\n/// | Position   | Field  | Type    | Bytes | Description                                             |\n/// | ---------- | ------ | ------- | ----- | ------------------------------------------------------- |\n/// | [000..017) | header | uint136 | 17    | Encoded general routing information for the message     |\n/// | [017..AAA) | body   | bytes   | ??    | Formatted payload (according to flag) with message body |\nlibrary MessageLib {\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MemViewLib for bytes;\n    using HeaderLib for MemView;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_HEADER = 0;\n    uint256 private constant OFFSET_BODY = OFFSET_HEADER + HEADER_LENGTH;\n\n    // ══════════════════════════════════════════════════ MESSAGE ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns formatted message with provided fields.\n     * @param header_   Encoded general routing information for the message\n     * @param body_     Formatted payload (according to flag) with message body\n     * @return Formatted message\n     */\n    function formatMessage(Header header_, bytes memory body_) internal pure returns (bytes memory) {\n        return abi.encodePacked(header_, body_);\n    }\n\n    /**\n     * @notice Returns a Message view over for the given payload.\n     * @dev Will revert if the payload is not a message payload.\n     */\n    function castToMessage(bytes memory payload) internal pure returns (Message) {\n        return castToMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Message view.\n     * @dev Will revert if the memory view is not over a message payload.\n     */\n    function castToMessage(MemView memView) internal pure returns (Message) {\n        if (!isMessage(memView)) revert UnformattedMessage();\n        return Message.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Message.\n     */\n    function isMessage(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Check if headers exist in the payload\n        if (length \u003c OFFSET_BODY) return false;\n        // Check that Header is valid\n        uint256 paddedHeader = _header(memView);\n        if (!HeaderLib.isHeader(paddedHeader)) return false;\n        // Check that body is formatted according to the flag\n        // Only Base/Manager message flags exist\n        if (HeaderLib.wrapPadded(paddedHeader).flag() == MessageFlag.Base) {\n            // Check if body is a formatted base message\n            return _body(memView).isBaseMessage();\n        } else {\n            // Check if body is a formatted calldata for AgentManager call\n            return _body(memView).isCallData();\n        }\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Message message) internal pure returns (MemView) {\n        return MemView.wrap(Message.unwrap(message));\n    }\n\n    /// @notice Returns message's hash: a leaf to be inserted in the Merkle tree.\n    function leaf(Message message) internal pure returns (bytes32) {\n        // We hash header and body separately to make message proofs easier to verify\n        Header header_ = message.header();\n        // Only Base/Manager message flags exist\n        if (header_.flag() == MessageFlag.Base) {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToBaseMessage().leaf());\n        } else {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToCallData().leaf());\n        }\n    }\n\n    // ══════════════════════════════════════════════ MESSAGE SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns message's encoded header field.\n    function header(Message message) internal pure returns (Header) {\n        return HeaderLib.wrapPadded((message.unwrap().indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH})));\n    }\n\n    /// @notice Returns message's body field as an untyped memory view.\n    function body(Message message) internal pure returns (MemView) {\n        MemView memView = message.unwrap();\n        return _body(memView);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns message's padded header without checking that it is a valid header.\n    function _header(MemView memView) private pure returns (uint256) {\n        return memView.indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH});\n    }\n\n    /// @dev Returns an untyped memory view over the body field without checking\n    /// if the whole payload or the body are properly formatted.\n    function _body(MemView memView) private pure returns (MemView) {\n        return memView.sliceFrom({index_: OFFSET_BODY});\n    }\n}\n\n// contracts/base/AgentSecured.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for messaging contracts that are secured by the agent manager.\n * `AgentSecured` relies on `AgentManager` to provide the following functionality:\n * - Keep track of agents and their statuses.\n * - Pass agent-signed statements that were verified by the agent manager.\n * - These statements are considered valid indefinitely, unless the agent is disputed.\n * - Disputes are opened and resolved by the agent manager.\n * \u003e `AgentSecured` implementation should never use statements signed by agents that are disputed.\n */\nabstract contract AgentSecured is MessagingBase, IAgentSecured {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    address public immutable agentManager;\n\n    /// @inheritdoc IAgentSecured\n    address public immutable inbox;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    // (agent index =\u003e their dispute status: flag, openedAt, resolvedAt)\n    mapping(uint32 =\u003e DisputeStatus) internal _disputes;\n\n    /// @dev gap for upgrade safety\n    uint256[49] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    modifier onlyAgentManager() {\n        if (msg.sender != agentManager) revert CallerNotAgentManager();\n        _;\n    }\n\n    modifier onlyInbox() {\n        if (msg.sender != inbox) revert CallerNotInbox();\n        _;\n    }\n\n    constructor(string memory version_, uint32 synapseDomain_, address agentManager_, address inbox_)\n        MessagingBase(version_, synapseDomain_)\n    {\n        agentManager = agentManager_;\n        inbox = inbox_;\n    }\n\n    // ════════════════════════════════════════════ ONLY AGENT MANAGER ═════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external onlyAgentManager {\n        uint40 openedAt = ChainContext.blockTimestamp();\n        DisputeStatus memory status = DisputeStatus({flag: DisputeFlag.Pending, openedAt: openedAt, resolvedAt: 0});\n        _disputes[guardIndex] = status;\n        _disputes[notaryIndex] = status;\n    }\n\n    /// @inheritdoc IAgentSecured\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external onlyAgentManager {\n        // Update the dispute status of the slashed agent first.\n        uint40 resolvedAt = ChainContext.blockTimestamp();\n        _disputes[slashedIndex].flag = DisputeFlag.Slashed;\n        _disputes[slashedIndex].resolvedAt = resolvedAt;\n        // Mark the rival agent as not disputed, if there was an ongoing dispute.\n        if (rivalIndex != 0) {\n            _disputes[rivalIndex].flag = DisputeFlag.None;\n            _disputes[rivalIndex].resolvedAt = resolvedAt;\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function agentStatus(address agent) external view returns (AgentStatus memory) {\n        return _agentStatus(agent);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status) {\n        return _getAgent(index);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory) {\n        return _disputes[agentIndex];\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns status of the given agent: (flag, domain, index).\n    function _agentStatus(address agent) internal view returns (AgentStatus memory) {\n        return IAgentManager(agentManager).agentStatus(agent);\n    }\n\n    /// @dev Returns agent and their status for a given agent index. Returns zero values for non existing indexes.\n    function _getAgent(uint256 index) internal view returns (address agent, AgentStatus memory status) {\n        return IAgentManager(agentManager).getAgent(index);\n    }\n\n    /// @dev Checks if a Dispute exists for the given Notary. This function returns true, if\n    /// Notary is in ongoing Dispute, or if Dispute was resolved not in Notary's favor.\n    /// In both cases we can't trust Notary's data.\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeExists(uint32 notaryIndex) internal view returns (bool) {\n        return _disputes[notaryIndex].flag != DisputeFlag.None;\n    }\n\n    /// @dev Checks if a Notary recently won a Dispute and is still in the \"post-dispute\" timeout period.\n    /// In this period we still can't trust Notary's data, though we can optimistically assume that\n    /// that the data will be correct after the timeout (assuming no new Disputes are opened).\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeTimeout(uint32 notaryIndex) internal view returns (bool) {\n        DisputeStatus memory status = _disputes[notaryIndex];\n        // Exit early if Notary is in ongoing Dispute / slashed.\n        if (status.flag != DisputeFlag.None) return false;\n        // Check if Notary has been in any Dispute at all.\n        if (status.openedAt == 0) return false;\n        // Otherwise check if the Dispute timeout is still active.\n        return block.timestamp \u003c status.resolvedAt + DISPUTE_TIMEOUT_NOTARY;\n    }\n}\n\n// contracts/hubs/StateHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StateHub` is a parent contract for `Origin`. It is responsible for the following:\n/// - Keeping track of the historical Origin Merkle Tree containing all the message hashes.\n/// - Keeping track of the historical Origin States, as well as verifying their validity.\nabstract contract StateHub is AgentSecured, StateHubEvents, IStateHub {\n    using SafeCast for uint256;\n    using StateLib for bytes;\n\n    struct OriginState {\n        uint40 blockNumber;\n        uint40 timestamp;\n        GasData gasData;\n    }\n    // Bits left for tight packing: 80\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Historical Merkle Tree\n    /// Note: Takes two storage slots\n    HistoricalTree private _tree;\n\n    /// @dev All historical contract States\n    OriginState[] private _originStates;\n\n    /// @dev gap for upgrade safety\n    uint256[47] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IStateHub\n    function isValidState(bytes memory statePayload) external view returns (bool isValid) {\n        // This will revert if payload is not a formatted state\n        State state = statePayload.castToState();\n        return _isValidState(state);\n    }\n\n    /// @inheritdoc IStateHub\n    function statesAmount() external view returns (uint256) {\n        return _originStates.length;\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestLatestState() external view returns (bytes memory stateData) {\n        // This never underflows, assuming the contract was initialized\n        return suggestState(_nextNonce() - 1);\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestState(uint32 nonce) public view returns (bytes memory stateData) {\n        // This will revert if nonce is out of range\n        bytes32 root = _tree.root(nonce);\n        return _formatOriginState(_originStates[nonce], root, localDomain, nonce);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Initializes the saved states list by inserting a state for an empty Merkle Tree.\n    function _initializeStates() internal {\n        // This should only be called once, when the contract is initialized\n        // This will revert if _tree.roots is non-empty\n        bytes32 savedRoot = _tree.initializeRoots();\n        // Save root for empty merkle _tree with block number and timestamp of initialization\n        _saveState(savedRoot, _toOriginState());\n    }\n\n    /// @dev Inserts leaf into the Merkle Tree and saves the updated origin State.\n    function _insertAndSave(bytes32 leaf) internal {\n        bytes32 newRoot = _tree.insert(leaf);\n        _saveState(newRoot, _toOriginState());\n    }\n\n    /// @dev Saves an updated state of the Origin contract\n    function _saveState(bytes32 root, OriginState memory state) internal {\n        uint32 nonce = _nextNonce();\n        _originStates.push(state);\n        // Emit event with raw state data\n        emit StateSaved(_formatOriginState(state, root, localDomain, nonce));\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns nonce of the next sent message: the amount of saved States so far.\n    /// This always equals to \"total amount of sent messages\" plus 1.\n    function _nextNonce() internal view returns (uint32) {\n        // TODO: consider using more than 32 bits for origin nonces\n        return _originStates.length.toUint32();\n    }\n\n    /// @dev Checks if a state is valid, i.e. if it matches the historical one.\n    /// Reverts, if state refers to another Origin contract.\n    function _isValidState(State state) internal view returns (bool) {\n        // Check if state refers to this contract\n        if (state.origin() != localDomain) revert IncorrectOriginDomain();\n        // Check if nonce exists\n        uint32 nonce = state.nonce();\n        if (nonce \u003e= _originStates.length) return false;\n        // Check if state root matches the historical one\n        if (state.root() != _tree.root(nonce)) return false;\n        // Check if state metadata matches the historical one\n        return _areEqual(state, _originStates[nonce]);\n    }\n\n    // ═════════════════════════════════════════════ STRUCT FORMATTING ═════════════════════════════════════════════════\n\n    /// @dev Returns a formatted payload for a stored OriginState.\n    function _formatOriginState(OriginState memory originState, bytes32 root, uint32 origin, uint32 nonce)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return StateLib.formatState({\n            root_: root,\n            origin_: origin,\n            nonce_: nonce,\n            blockNumber_: originState.blockNumber,\n            timestamp_: originState.timestamp,\n            gasData_: originState.gasData\n        });\n    }\n\n    /// @dev Child contract should implement the logic for getting the current gas data from the gas oracle\n    /// to be saved as part of the Origin State.\n    // solhint-disable-next-line ordering\n    function _fetchGasData() internal view virtual returns (GasData);\n\n    /// @dev Returns a OriginState struct to save in the contract.\n    function _toOriginState() internal view returns (OriginState memory originState) {\n        originState.blockNumber = ChainContext.blockNumber();\n        originState.timestamp = ChainContext.blockTimestamp();\n        originState.gasData = _fetchGasData();\n    }\n\n    /// @dev Checks that a state and its Origin representation are equal.\n    function _areEqual(State state, OriginState memory originState) internal pure returns (bool) {\n        return state.blockNumber() == originState.blockNumber \u0026\u0026 state.timestamp() == originState.timestamp;\n    }\n}\n\n// contracts/Origin.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Origin` contract is used for sending messages to remote chains. It is done\n/// by inserting the message hashes into the Origin Merkle, which makes it possible to\n/// prove that message was sent using the Merkle proof against the Origin Merkle Root. This essentially\n/// compresses the list of messages into a single 32-byte value that needs to be stored on the destination chain.\n/// `Origin` is responsible for the following:\n/// - Formatting the sent message payloads, and inserting their hashes into the Origin Merkle Tree.\n/// - Keeping track of its own historical states (see parent contract `StateHub`).\n/// - Enforcing minimum tip values for sent base messages based on the provided execution requests.\n/// - Distributing the collected tips upon request from a local `AgentManager` contract.\ncontract Origin is StateHub, OriginEvents, InterfaceOrigin {\n    using MemViewLib for bytes;\n    using MessageLib for bytes;\n    using TipsLib for bytes;\n    using TypeCasts for address;\n\n    address public immutable gasOracle;\n\n    modifier onlyRemoteDestination(uint32 destination) {\n        if (destination == localDomain) revert IncorrectDestinationDomain();\n        _;\n    }\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_, address gasOracle_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {\n        gasOracle = gasOracle_;\n    }\n\n    /// @notice Initializes Origin contract:\n    /// - msg.sender is set as contract owner\n    /// - State of \"empty merkle tree\" is saved\n    function initialize() external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize \"states\": state of an \"empty merkle tree\" is saved\n        _initializeStates();\n    }\n\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable onlyRemoteDestination(destination) returns (uint32 messageNonce, bytes32 messageHash) {\n        // Check that content is not too large\n        if (content.length \u003e MAX_CONTENT_BYTES) revert ContentLengthTooBig();\n        // This will revert if msg.value is lower than value of minimum tips\n        Tips tips = _getMinimumTips(destination, paddedRequest, content.length).matchValue(msg.value);\n        Request request = RequestLib.wrapPadded(paddedRequest);\n        // Format the BaseMessage body\n        bytes memory body = BaseMessageLib.formatBaseMessage({\n            sender_: msg.sender.addressToBytes32(),\n            recipient_: recipient,\n            tips_: tips,\n            request_: request,\n            content_: content\n        });\n        // Send the message\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Base, body);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        onlyAgentManager\n        onlyRemoteDestination(destination)\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // AgentManager (checked via modifier) is responsible for constructing the calldata payload correctly.\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Manager, payload);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function withdrawTips(address recipient, uint256 amount) external onlyAgentManager {\n        if (address(this).balance \u003c amount) revert InsufficientEthBalance();\n        (bool success,) = recipient.call{value: amount}(\"\");\n        if (!success) revert EthTransferFailed();\n        emit TipWithdrawalCompleted(recipient, amount);\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue)\n    {\n        return _getMinimumTips(destination, paddedRequest, contentLength).value();\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Sends the given message to the specified destination. Message hash is inserted\n    /// into the Origin Merkle Tree, which will enable message execution on destination chain.\n    function _sendMessage(uint32 destination, uint32 optimisticPeriod, MessageFlag flag, bytes memory body)\n        internal\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // Format the message header\n        messageNonce = _nextNonce();\n        Header header = flag.encodeHeader({\n            origin_: localDomain,\n            nonce_: messageNonce,\n            destination_: destination,\n            optimisticPeriod_: optimisticPeriod\n        });\n        // Format the full message payload\n        bytes memory msgPayload = MessageLib.formatMessage(header, body);\n        // Insert new leaf into the Origin Merkle Tree and save the updated state\n        messageHash = msgPayload.castToMessage().leaf();\n        _insertAndSave(messageHash);\n        // Emit event with message information\n        emit Sent(messageHash, messageNonce, destination, msgPayload);\n        // Update the gas oracle data. We do this after the provided tips are checked so that\n        // the provided message is sent in the event that the gas oracle data is updated to a higher value.\n        InterfaceGasOracle(gasOracle).updateGasData(destination);\n        // TODO: consider doing this before the message is sent, while adjusting GasOracle.getMinimumTips() to\n        // use the pending gas oracle data.\n    }\n\n    /// @dev Returns the minimum tips for sending a message to the given destination with the given request and content.\n    function _getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        internal\n        view\n        returns (Tips)\n    {\n        return\n            TipsLib.wrapPadded(InterfaceGasOracle(gasOracle).getMinimumTips(destination, paddedRequest, contentLength));\n    }\n\n    /// @dev Gets the current gas data from the gas oracle to be saved as part of the Origin State.\n    function _fetchGasData() internal view override returns (GasData) {\n        return GasDataLib.wrapGasData(InterfaceGasOracle(gasOracle).getGasData());\n    }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"143597:9194:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;143597:9194:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"143597:9194:0:-:0;;;;;;;;","abiDefinition":[],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"kind":"dev","methods":{},"stateVariables":{"SELECTOR_LENGTH":{"details":"Calldata memory layout [000 .. 004) selector    bytes4  4 bytes      Optional: N function arguments [004 .. 036) arg1        bytes32 32 bytes      .. [AAA .. END) argN        bytes32 32 bytes"},"SIGNATURE_LENGTH":{"details":"non-compact ECDSA signatures are enforced as of OZ 4.7.3      Signature payload memory layout [000 .. 032) r   bytes32 32 bytes [032 .. 064) s   bytes32 32 bytes [064 .. 065) v   uint8    1 byte"}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"stateVariables\":{\"SELECTOR_LENGTH\":{\"details\":\"Calldata memory layout [000 .. 004) selector    bytes4  4 bytes      Optional: N function arguments [004 .. 036) arg1        bytes32 32 bytes      .. [AAA .. END) argN        bytes32 32 bytes\"},\"SIGNATURE_LENGTH\":{\"details\":\"non-compact ECDSA signatures are enforced as of OZ 4.7.3      Signature payload memory layout [000 .. 032) r   bytes32 32 bytes [032 .. 064) s   bytes32 32 bytes [064 .. 065) v   uint8    1 byte\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Origin.sol\":\"ByteString\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Origin.sol\":{\"keccak256\":\"0x96775924f147f3d1f8df8cdf56731fe52a15af8d8e12e608efb8158c112b18cd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e642a27f5fab3c62b4c02e9754e9e42b1cf2e5381dbea9d3d106d23b7772ebe6\",\"dweb:/ipfs/QmUwn7ZyBvPkjnMuK8ZMSexBUdNQnVtxwyoAyT4DXLQjra\"]}},\"version\":1}"},"hashes":{}},"solidity/Origin.sol:ChainContext":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212202bb1046012e3a703e42bc48646aed5c9673c49908bb5ab6e4ce18c6fb8a9f55b64736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212202bb1046012e3a703e42bc48646aed5c9673c49908bb5ab6e4ce18c6fb8a9f55b64736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/OriginEvents.sol\n\n/// @notice A collection of events emitted by the Origin contract\nabstract contract OriginEvents {\n    /**\n     * @notice Emitted when a new message is sent.\n     * @param messageHash   Hash of message; the leaf inserted to the Merkle tree for the message\n     * @param nonce         Nonce of sent message (starts from 1)\n     * @param destination   Destination domain\n     * @param message       Raw bytes of message\n     */\n    event Sent(bytes32 indexed messageHash, uint32 indexed nonce, uint32 indexed destination, bytes message);\n\n    /**\n     * @notice Emitted when a tip withdrawal is completed.\n     * @param actor     Actor address\n     * @param tip       Tip value, denominated in local domain's wei\n     */\n    event TipWithdrawalCompleted(address actor, uint256 tip);\n}\n\n// contracts/events/StateHubEvents.sol\n\n/// @notice A collection of events emitted by the StateHub contract\nabstract contract StateHubEvents {\n    /**\n     * @notice Emitted when a new Origin State is saved after a message was sent.\n     * @param state     Raw payload with state data\n     */\n    event StateSaved(bytes state);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n    /**\n     * @notice Check that a given state is valid: matches the historical state of Origin contract.\n     * Note: any Agent including an invalid state in their snapshot will be slashed\n     * upon providing the snapshot and agent signature for it to Origin contract.\n     * @dev Will revert if any of these is true:\n     *  - State payload is not properly formatted.\n     * @param statePayload      Raw payload with state data\n     * @return isValid          Whether the provided state is valid\n     */\n    function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns the amount of saved states so far.\n     * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n     */\n    function statesAmount() external view returns (uint256);\n\n    /**\n     * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @return statePayload     Raw payload with the latest state data\n     */\n    function suggestLatestState() external view returns (bytes memory statePayload);\n\n    /**\n     * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @param nonce             Historical nonce to form a state\n     * @return statePayload     Raw payload with historical state data\n     */\n    function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/InterfaceGasOracle.sol\n\ninterface InterfaceGasOracle {\n    /**\n     * @notice Fetches the latest gas data for the chain from `Destination` contract,\n     * and uses it to update the oracle values for the requested chain.\n     * @param domain    Domain to update the gas data for\n     */\n    function updateGasData(uint32 domain) external;\n\n    /**\n     * @notice Returns the gas data for the local chain.\n     */\n    function getGasData() external view returns (uint256 paddedGasData);\n\n    /**\n     * @notice Returns the gas data for the given domain, in the decoded format.\n     * @param domain        Domain of chain to get gas data for\n     * @return gasPrice     Gas price for the chain (in Wei per gas unit)\n     * @return dataPrice    Calldata price (in Wei per byte of content)\n     * @return execBuffer   Tx fee safety buffer for message execution (in Wei)\n     * @return amortAttCost Amortized cost for attestation submission (in Wei)\n     * @return etherPrice   Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n     * @return markup       Markup for the message execution (in BWAD)\n     */\n    function getDecodedGasData(uint32 domain)\n        external\n        view\n        returns (\n            uint256 gasPrice,\n            uint256 dataPrice,\n            uint256 execBuffer,\n            uint256 amortAttCost,\n            uint256 etherPrice,\n            uint256 markup\n        );\n\n    /**\n     * @notice Returns the minimum tips for sending a message to a given destination.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return paddedTips       Padded encoded minimum tips information\n     */\n    function getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 paddedTips);\n}\n\n// contracts/interfaces/InterfaceOrigin.sol\n\ninterface InterfaceOrigin {\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /**\n     * @notice Send a message to the recipient located on destination domain.\n     * @dev Recipient has to conform to IMessageRecipient interface, otherwise message won't be delivered.\n     * Will revert if any of these is true:\n     * - `destination` is equal to contract's local domain\n     * - `content` length is greater than `MAX_CONTENT_BYTES`\n     * - `msg.value` is lower than value of minimum tips for the given message\n     * @param destination           Domain of destination chain\n     * @param recipient             Address of recipient on destination chain as bytes32\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param paddedRequest         Padded encoded message execution request on destination chain\n     * @param content               Raw bytes content of message\n     * @return messageNonce         Nonce of the sent message\n     * @return messageHash          Hash of the sent message\n     */\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable returns (uint32 messageNonce, bytes32 messageHash);\n\n    /**\n     * @notice Send a manager message to the destination domain.\n     * @dev This could only be called by AgentManager, which takes care of encoding the calldata payload.\n     * Note: (msgOrigin, proofMaturity) security args will be added to payload on the destination chain\n     * so that the AgentManager could verify where the Manager Message came from and how mature is the proof.\n     * Note: function is not payable, as no tips are required for sending a manager message.\n     * Will revert if `destination` is equal to contract's local domain.\n     * @param destination           Domain of destination chain\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param payload               Payload for calling AgentManager on destination chain (with extra security args)\n     */\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        returns (uint32 messageNonce, bytes32 messageHash);\n\n    // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Withdraws locked base message tips to the recipient.\n     * @dev Could only be called by a local AgentManager.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function withdrawTips(address recipient, uint256 amount) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the minimum tips value for sending a message to a given destination.\n     * @dev Using at least `tipsValue` as `msg.value` for `sendBaseMessage()`\n     * will guarantee that the message will be accepted.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return tipsValue        Minimum tips value for a message to be accepted\n     */\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue);\n}\n\n// contracts/libs/Constants.sol\n\n// Here we define common constants to enable their easier reusing later.\n\n// ══════════════════════════════════ MERKLE ═══════════════════════════════════\n/// @dev Height of the Agent Merkle Tree\nuint256 constant AGENT_TREE_HEIGHT = 32;\n/// @dev Height of the Origin Merkle Tree\nuint256 constant ORIGIN_TREE_HEIGHT = 32;\n/// @dev Height of the Snapshot Merkle Tree. Allows up to 64 leafs, e.g. up to 32 states\nuint256 constant SNAPSHOT_TREE_HEIGHT = 6;\n// ══════════════════════════════════ STRUCTS ══════════════════════════════════\n/// @dev See Attestation.sol: (bytes32,bytes32,uint32,uint40,uint40): 32+32+4+5+5\nuint256 constant ATTESTATION_LENGTH = 78;\n/// @dev See GasData.sol: (uint16,uint16,uint16,uint16,uint16,uint16): 2+2+2+2+2+2\nuint256 constant GAS_DATA_LENGTH = 12;\n/// @dev See Receipt.sol: (uint32,uint32,bytes32,bytes32,uint8,address,address,address): 4+4+32+32+1+20+20+20\nuint256 constant RECEIPT_LENGTH = 133;\n/// @dev See State.sol: (bytes32,uint32,uint32,uint40,uint40,GasData): 32+4+4+5+5+len(GasData)\nuint256 constant STATE_LENGTH = 50 + GAS_DATA_LENGTH;\n/// @dev Maximum amount of states in a single snapshot. Each state produces two leafs in the tree\nuint256 constant SNAPSHOT_MAX_STATES = 1 \u003c\u003c (SNAPSHOT_TREE_HEIGHT - 1);\n// ══════════════════════════════════ MESSAGE ══════════════════════════════════\n/// @dev See Header.sol: (uint8,uint32,uint32,uint32,uint32): 1+4+4+4+4\nuint256 constant HEADER_LENGTH = 17;\n/// @dev See Request.sol: (uint96,uint64,uint32): 12+8+4\nuint256 constant REQUEST_LENGTH = 24;\n/// @dev See Tips.sol: (uint64,uint64,uint64,uint64): 8+8+8+8\nuint256 constant TIPS_LENGTH = 32;\n/// @dev The amount of discarded last bits when encoding tip values\nuint256 constant TIPS_GRANULARITY = 32;\n/// @dev Tip values could be only the multiples of TIPS_MULTIPLIER\nuint256 constant TIPS_MULTIPLIER = 1 \u003c\u003c TIPS_GRANULARITY;\n// ══════════════════════════════ STATEMENT SALTS ══════════════════════════════\n/// @dev Salts for signing various statements\nbytes32 constant ATTESTATION_VALID_SALT = keccak256(\"ATTESTATION_VALID_SALT\");\nbytes32 constant ATTESTATION_INVALID_SALT = keccak256(\"ATTESTATION_INVALID_SALT\");\nbytes32 constant RECEIPT_VALID_SALT = keccak256(\"RECEIPT_VALID_SALT\");\nbytes32 constant RECEIPT_INVALID_SALT = keccak256(\"RECEIPT_INVALID_SALT\");\nbytes32 constant SNAPSHOT_VALID_SALT = keccak256(\"SNAPSHOT_VALID_SALT\");\nbytes32 constant STATE_INVALID_SALT = keccak256(\"STATE_INVALID_SALT\");\n// ═════════════════════════════════ PROTOCOL ══════════════════════════════════\n/// @dev Optimistic period for new agent roots in LightManager\nuint32 constant AGENT_ROOT_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Timeout between the agent root could be proposed and resolved in LightManager\nuint32 constant AGENT_ROOT_PROPOSAL_TIMEOUT = 12 hours;\nuint32 constant BONDING_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Amount of time that the Notary will not be considered active after they won a dispute\nuint32 constant DISPUTE_TIMEOUT_NOTARY = 12 hours;\n/// @dev Amount of time without fresh data from Notaries before contract owner can resolve stuck disputes manually\nuint256 constant FRESH_DATA_TIMEOUT = 4 hours;\n/// @dev Maximum bytes per message = 2 KiB (somewhat arbitrarily set to begin)\nuint256 constant MAX_CONTENT_BYTES = 2 * 2 ** 10;\n/// @dev Maximum value for the summit tip that could be set in GasOracle\nuint256 constant MAX_SUMMIT_TIP = 0.01 ether;\n\n// contracts/libs/Errors.sol\n\n// ══════════════════════════════ INVALID CALLER ═══════════════════════════════\n\nerror CallerNotAgentManager();\nerror CallerNotDestination();\nerror CallerNotInbox();\nerror CallerNotSummit();\n\n// ══════════════════════════════ INCORRECT DATA ═══════════════════════════════\n\nerror IncorrectAttestation();\nerror IncorrectAgentDomain();\nerror IncorrectAgentIndex();\nerror IncorrectAgentProof();\nerror IncorrectAgentRoot();\nerror IncorrectDataHash();\nerror IncorrectDestinationDomain();\nerror IncorrectOriginDomain();\nerror IncorrectSnapshotProof();\nerror IncorrectSnapshotRoot();\nerror IncorrectState();\nerror IncorrectStatesAmount();\nerror IncorrectTipsProof();\nerror IncorrectVersionLength();\n\nerror IncorrectNonce();\nerror IncorrectSender();\nerror IncorrectRecipient();\n\nerror FlagOutOfRange();\nerror IndexOutOfRange();\nerror NonceOutOfRange();\n\nerror OutdatedNonce();\n\nerror UnformattedAttestation();\nerror UnformattedAttestationReport();\nerror UnformattedBaseMessage();\nerror UnformattedCallData();\nerror UnformattedCallDataPrefix();\nerror UnformattedMessage();\nerror UnformattedReceipt();\nerror UnformattedReceiptReport();\nerror UnformattedSignature();\nerror UnformattedSnapshot();\nerror UnformattedState();\nerror UnformattedStateReport();\n\n// ═══════════════════════════════ MERKLE TREES ════════════════════════════════\n\nerror LeafNotProven();\nerror MerkleTreeFull();\nerror NotEnoughLeafs();\nerror TreeHeightTooLow();\n\n// ═════════════════════════════ OPTIMISTIC PERIOD ═════════════════════════════\n\nerror BaseClientOptimisticPeriod();\nerror MessageOptimisticPeriod();\nerror SlashAgentOptimisticPeriod();\nerror WithdrawTipsOptimisticPeriod();\nerror ZeroProofMaturity();\n\n// ═══════════════════════════════ AGENT MANAGER ═══════════════════════════════\n\nerror AgentNotGuard();\nerror AgentNotNotary();\n\nerror AgentCantBeAdded();\nerror AgentNotActive();\nerror AgentNotActiveNorUnstaking();\nerror AgentNotFraudulent();\nerror AgentNotUnstaking();\nerror AgentUnknown();\n\nerror AgentRootNotProposed();\nerror AgentRootTimeoutNotOver();\n\nerror NotStuck();\n\nerror DisputeAlreadyResolved();\nerror DisputeNotOpened();\nerror DisputeTimeoutNotOver();\nerror GuardInDispute();\nerror NotaryInDispute();\n\nerror MustBeSynapseDomain();\nerror SynapseDomainForbidden();\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\nerror AlreadyExecuted();\nerror AlreadyFailed();\nerror DuplicatedSnapshotRoot();\nerror IncorrectMagicValue();\nerror GasLimitTooLow();\nerror GasSuppliedTooLow();\n\n// ══════════════════════════════════ ORIGIN ═══════════════════════════════════\n\nerror ContentLengthTooBig();\nerror EthTransferFailed();\nerror InsufficientEthBalance();\n\n// ════════════════════════════════ GAS ORACLE ═════════════════════════════════\n\nerror LocalGasDataNotSet();\nerror RemoteGasDataNotSet();\n\n// ═══════════════════════════════════ TIPS ════════════════════════════════════\n\nerror SummitTipTooHigh();\nerror TipsClaimMoreThanEarned();\nerror TipsClaimZero();\nerror TipsOverflow();\nerror TipsValueTooLow();\n\n// ════════════════════════════════ MEMORY VIEW ════════════════════════════════\n\nerror IndexedTooMuch();\nerror ViewOverrun();\nerror OccupiedMemory();\nerror UnallocatedMemory();\nerror PrecompileOutOfGas();\n\n// ═════════════════════════════════ MULTICALL ═════════════════════════════════\n\nerror MulticallFailed();\n\n// contracts/libs/TypeCasts.sol\n\nlibrary TypeCasts {\n    // alignment preserving cast\n    function addressToBytes32(address addr) internal pure returns (bytes32) {\n        return bytes32(uint256(uint160(addr)));\n    }\n\n    // alignment preserving cast\n    function bytes32ToAddress(bytes32 buf) internal pure returns (address) {\n        return address(uint160(uint256(buf)));\n    }\n}\n\n// contracts/libs/stack/Number.sol\n\n/// Number is a compact representation of uint256, that is fit into 16 bits\n/// with the maximum relative error under 0.4%.\ntype Number is uint16;\n\nusing NumberLib for Number global;\n\n/// # Number\n/// Library for compact representation of uint256 numbers.\n/// - Number is stored using mantissa and exponent, each occupying 8 bits.\n/// - Numbers under 2**8 are stored as `mantissa` with `exponent = 0xFF`.\n/// - Numbers at least 2**8 are approximated as `(256 + mantissa) \u003c\u003c exponent`\n/// \u003e - `0 \u003c= mantissa \u003c 256`\n/// \u003e - `0 \u003c= exponent \u003c= 247` (`256 * 2**248` doesn't fit into uint256)\n/// # Number stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type  | Bytes |\n/// | ---------- | -------- | ----- | ----- |\n/// | (002..001] | mantissa | uint8 | 1     |\n/// | (001..000] | exponent | uint8 | 1     |\n\nlibrary NumberLib {\n    /// @dev Amount of bits to shift to mantissa field\n    uint16 private constant SHIFT_MANTISSA = 8;\n\n    /// @notice For bwad math (binary wad) we use 2**64 as \"wad\" unit.\n    /// @dev We are using not using 10**18 as wad, because it is not stored precisely in NumberLib.\n    uint256 internal constant BWAD_SHIFT = 64;\n    uint256 internal constant BWAD = 1 \u003c\u003c BWAD_SHIFT;\n    /// @notice ~0.1% in bwad units.\n    uint256 internal constant PER_MILLE_SHIFT = BWAD_SHIFT - 10;\n    uint256 internal constant PER_MILLE = 1 \u003c\u003c PER_MILLE_SHIFT;\n\n    /// @notice Compresses uint256 number into 16 bits.\n    function compress(uint256 value) internal pure returns (Number) {\n        // Find `msb` such as `2**msb \u003c= value \u003c 2**(msb + 1)`\n        uint256 msb = mostSignificantBit(value);\n        // We want to preserve 9 bits of precision.\n        // The highest bit is always 1, so we can skip it.\n        // The remaining 8 highest bits are stored as mantissa.\n        if (msb \u003c 8) {\n            // Value is less than 2**8, so we can use value as mantissa with \"-1\" exponent.\n            return _encode(uint8(value), 0xFF);\n        } else {\n            // We use `msb - 8` as exponent otherwise. Note that `exponent \u003e= 0`.\n            unchecked {\n                uint256 exponent = msb - 8;\n                // Shifting right by `msb-8` bits will shift the \"remaining 8 highest bits\" into the 8 lowest bits.\n                // uint8() will truncate the highest bit.\n                return _encode(uint8(value \u003e\u003e exponent), uint8(exponent));\n            }\n        }\n    }\n\n    /// @notice Decompresses 16 bits number into uint256.\n    /// @dev The outcome is an approximation of the original number: `(value - value / 256) \u003c number \u003c= value`.\n    function decompress(Number number) internal pure returns (uint256 value) {\n        // Isolate 8 highest bits as the mantissa.\n        uint256 mantissa = Number.unwrap(number) \u003e\u003e SHIFT_MANTISSA;\n        // This will truncate the highest bits, leaving only the exponent.\n        uint256 exponent = uint8(Number.unwrap(number));\n        if (exponent == 0xFF) {\n            return mantissa;\n        } else {\n            unchecked {\n                return (256 + mantissa) \u003c\u003c (exponent);\n            }\n        }\n    }\n\n    /// @dev Returns the most significant bit of `x`\n    /// https://solidity-by-example.org/bitwise/\n    function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\n        // To find `msb` we determine it bit by bit, starting from the highest one.\n        // `0 \u003c= msb \u003c= 255`, so we start from the highest bit, 1\u003c\u003c7 == 128.\n        // If `x` is at least 2**128, then the highest bit of `x` is at least 128.\n        // solhint-disable no-inline-assembly\n        assembly {\n            // `f` is set to 1\u003c\u003c7 if `x \u003e= 2**128` and to 0 otherwise.\n            let f := shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\n            // If `x \u003e= 2**128` then set `msb` highest bit to 1 and shift `x` right by 128.\n            // Otherwise, `msb` remains 0 and `x` remains unchanged.\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        // `x` is now at most 2**128 - 1. Continue the same way, the next highest bit is 1\u003c\u003c6 == 64.\n        assembly {\n            // `f` is set to 1\u003c\u003c6 if `x \u003e= 2**64` and to 0 otherwise.\n            let f := shl(6, gt(x, 0xFFFFFFFFFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c5 if `x \u003e= 2**32` and to 0 otherwise.\n            let f := shl(5, gt(x, 0xFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c4 if `x \u003e= 2**16` and to 0 otherwise.\n            let f := shl(4, gt(x, 0xFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c3 if `x \u003e= 2**8` and to 0 otherwise.\n            let f := shl(3, gt(x, 0xFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c2 if `x \u003e= 2**4` and to 0 otherwise.\n            let f := shl(2, gt(x, 0xF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c1 if `x \u003e= 2**2` and to 0 otherwise.\n            let f := shl(1, gt(x, 0x3))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1 if `x \u003e= 2**1` and to 0 otherwise.\n            let f := gt(x, 0x1)\n            msb := or(msb, f)\n        }\n    }\n\n    /// @dev Wraps (mantissa, exponent) pair into Number.\n    function _encode(uint8 mantissa, uint8 exponent) private pure returns (Number) {\n        // Casts below are upcasts, so they are safe.\n        return Number.wrap(uint16(mantissa) \u003c\u003c SHIFT_MANTISSA | uint16(exponent));\n    }\n}\n\n// contracts/libs/stack/Request.sol\n\n/// Request is encoded data with \"message execution request\".\ntype Request is uint192;\n\nusing RequestLib for Request global;\n\n/// Library for formatting _the request part_ of _the base messages_.\n/// - Request represents a message sender requirements for the message execution on the destination chain.\n/// - Request occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n/// \u003e gasDrop field is included for future compatibility and is ignored at the moment.\n///\n/// # Request stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type   | Bytes | Description                                          |\n/// | ---------- | -------- | ------ | ----- | ---------------------------------------------------- |\n/// | (024..012] | gasDrop  | uint96 | 12    | Minimum amount of gas token to drop to the recipient |\n/// | (012..004] | gasLimit | uint64 | 8     | Minimum amount of gas units to supply for execution  |\n/// | (004..000] | version  | uint32 | 4     | Base message version to pass to the recipient        |\n\nlibrary RequestLib {\n    /// @dev Amount of bits to shift to gasDrop field\n    uint192 private constant SHIFT_GAS_DROP = 12 * 8;\n    /// @dev Amount of bits to shift to gasLimit field\n    uint192 private constant SHIFT_GAS_LIMIT = 4 * 8;\n\n    /// @notice Returns an encoded request with the given fields\n    /// @param gasDrop_     Minimum amount of gas token to drop to the recipient (ignored at the moment)\n    /// @param gasLimit_    Minimum amount of gas units to supply for execution\n    /// @param version_     Base message version to pass to the recipient\n    function encodeRequest(uint96 gasDrop_, uint64 gasLimit_, uint32 version_) internal pure returns (Request) {\n        // Casts below are upcasts, so they are safe\n        return Request.wrap(uint192(gasDrop_) \u003c\u003c SHIFT_GAS_DROP | uint192(gasLimit_) \u003c\u003c SHIFT_GAS_LIMIT | version_);\n    }\n\n    /// @notice Wraps the padded encoded request into a Request-typed value.\n    /// @dev The \"padded\" request is simply an encoded request casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded requests\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedRequest) internal pure returns (Request) {\n        // Casting to uint192 will truncate the highest bits, which is the behavior we want\n        return Request.wrap(uint192(paddedRequest));\n    }\n\n    /// @notice Returns the requested of gas token to drop to the recipient.\n    function gasDrop(Request request) internal pure returns (uint96) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return uint96(Request.unwrap(request) \u003e\u003e SHIFT_GAS_DROP);\n    }\n\n    /// @notice Returns the requested minimum amount of gas units to supply for execution.\n    function gasLimit(Request request) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Request.unwrap(request) \u003e\u003e SHIFT_GAS_LIMIT);\n    }\n\n    /// @notice Returns the requested base message version to pass to the recipient.\n    function version(Request request) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Request.unwrap(request));\n    }\n}\n\n// node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        require(value \u003c= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        require(value \u003c= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        require(value \u003c= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value \u003c= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        require(value \u003c= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        require(value \u003c= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        require(value \u003c= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        require(value \u003c= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        require(value \u003c= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        require(value \u003c= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        require(value \u003c= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        require(value \u003c= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        require(value \u003c= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        require(value \u003c= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        require(value \u003c= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value \u003c= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        require(value \u003c= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        require(value \u003c= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        require(value \u003c= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value \u003c= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        require(value \u003c= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        require(value \u003c= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        require(value \u003c= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value \u003c= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        require(value \u003c= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        require(value \u003c= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        require(value \u003c= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value \u003c= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        require(value \u003c= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value \u003c= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value \u003c= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     *\n     * _Available since v3.0._\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value \u003e= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     *\n     * _Available since v3.0._\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value \u003c= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     *\n     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length \u003e 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance \u003e= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance \u003e= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length \u003e 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n\n// contracts/base/MultiCallable.sol\n\n/// @notice Collection of Multicall utilities. Fork of Multicall3:\n/// https://github.com/mds1/multicall/blob/master/src/Multicall3.sol\nabstract contract MultiCallable {\n    struct Call {\n        bool allowFailure;\n        bytes callData;\n    }\n\n    struct Result {\n        bool success;\n        bytes returnData;\n    }\n\n    /// @notice Aggregates a few calls to this contract into one multicall without modifying `msg.sender`.\n    function multicall(Call[] calldata calls) external returns (Result[] memory callResults) {\n        uint256 amount = calls.length;\n        callResults = new Result[](amount);\n        Call calldata call_;\n        for (uint256 i = 0; i \u003c amount;) {\n            call_ = calls[i];\n            Result memory result = callResults[i];\n            // We perform a delegate call to ourselves here. Delegate call does not modify `msg.sender`, so\n            // this will have the same effect as if `msg.sender` performed all the calls themselves one by one.\n            // solhint-disable-next-line avoid-low-level-calls\n            (result.success, result.returnData) = address(this).delegatecall(call_.callData);\n            // solhint-disable-next-line no-inline-assembly\n            assembly {\n                // Revert if the call fails and failure is not allowed\n                // `allowFailure := calldataload(call_)` and `success := mload(result)`\n                if iszero(or(calldataload(call_), mload(result))) {\n                    // Revert with `0x4d6a2328` (function selector for `MulticallFailed()`)\n                    mstore(0x00, 0x4d6a232800000000000000000000000000000000000000000000000000000000)\n                    revert(0x00, 0x04)\n                }\n            }\n            unchecked {\n                ++i;\n            }\n        }\n    }\n}\n\n// contracts/base/Version.sol\n\n/**\n * @title Versioned\n * @notice Version getter for contracts. Doesn't use any storage slots, meaning\n * it will never cause any troubles with the upgradeable contracts. For instance, this contract\n * can be added or removed from the inheritance chain without shifting the storage layout.\n */\nabstract contract Versioned {\n    /**\n     * @notice Struct that is mimicking the storage layout of a string with 32 bytes or less.\n     * Length is limited by 32, so the whole string payload takes two memory words:\n     * @param length    String length\n     * @param data      String characters\n     */\n    struct _ShortString {\n        uint256 length;\n        bytes32 data;\n    }\n\n    /// @dev Length of the \"version string\"\n    uint256 private immutable _length;\n    /// @dev Bytes representation of the \"version string\".\n    /// Strings with length over 32 are not supported!\n    bytes32 private immutable _data;\n\n    constructor(string memory version_) {\n        _length = bytes(version_).length;\n        if (_length \u003e 32) revert IncorrectVersionLength();\n        // bytes32 is left-aligned =\u003e this will store the byte representation of the string\n        // with the trailing zeroes to complete the 32-byte word\n        _data = bytes32(bytes(version_));\n    }\n\n    function version() external view returns (string memory versionString) {\n        // Load the immutable values to form the version string\n        _ShortString memory str = _ShortString(_length, _data);\n        // The only way to do this cast is doing some dirty assembly\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            versionString := str\n        }\n    }\n}\n\n// contracts/libs/ChainContext.sol\n\n/// @notice Library for accessing chain context variables as tightly packed integers.\n/// Messaging contracts should rely on this library for accessing chain context variables\n/// instead of doing the casting themselves.\nlibrary ChainContext {\n    using SafeCast for uint256;\n\n    /// @notice Returns the current block number as uint40.\n    /// @dev Reverts if block number is greater than 40 bits, which is not supposed to happen\n    /// until the block.timestamp overflows (assuming block time is at least 1 second).\n    function blockNumber() internal view returns (uint40) {\n        return block.number.toUint40();\n    }\n\n    /// @notice Returns the current block timestamp as uint40.\n    /// @dev Reverts if block timestamp is greater than 40 bits, which is\n    /// supposed to happen approximately in year 36835.\n    function blockTimestamp() internal view returns (uint40) {\n        return block.timestamp.toUint40();\n    }\n\n    /// @notice Returns the chain id as uint32.\n    /// @dev Reverts if chain id is greater than 32 bits, which is not\n    /// supposed to happen in production.\n    function chainId() internal view returns (uint32) {\n        return block.chainid.toUint32();\n    }\n}\n\n// contracts/libs/Structures.sol\n\n// Here we define common enums and structures to enable their easier reusing later.\n\n// ═══════════════════════════════ AGENT STATUS ════════════════════════════════\n\n/// @dev Potential statuses for the off-chain bonded agent:\n/// - Unknown: never provided a bond =\u003e signature not valid\n/// - Active: has a bond in BondingManager =\u003e signature valid\n/// - Unstaking: has a bond in BondingManager, initiated the unstaking =\u003e signature not valid\n/// - Resting: used to have a bond in BondingManager, successfully unstaked =\u003e signature not valid\n/// - Fraudulent: proven to commit fraud, value in Merkle Tree not updated =\u003e signature not valid\n/// - Slashed: proven to commit fraud, value in Merkle Tree was updated =\u003e signature not valid\n/// Unstaked agent could later be added back to THE SAME domain by staking a bond again.\n/// Honest agent: Unknown -\u003e Active -\u003e unstaking -\u003e Resting -\u003e Active ...\n/// Malicious agent: Unknown -\u003e Active -\u003e Fraudulent -\u003e Slashed\n/// Malicious agent: Unknown -\u003e Active -\u003e Unstaking -\u003e Fraudulent -\u003e Slashed\nenum AgentFlag {\n    Unknown,\n    Active,\n    Unstaking,\n    Resting,\n    Fraudulent,\n    Slashed\n}\n\n/// @notice Struct for storing an agent in the BondingManager contract.\nstruct AgentStatus {\n    AgentFlag flag;\n    uint32 domain;\n    uint32 index;\n}\n// 184 bits available for tight packing\n\nusing StructureUtils for AgentStatus global;\n\n/// @notice Potential statuses of an agent in terms of being in dispute\n/// - None: agent is not in dispute\n/// - Pending: agent is in unresolved dispute\n/// - Slashed: agent was in dispute that lead to agent being slashed\n/// Note: agent who won the dispute has their status reset to None\nenum DisputeFlag {\n    None,\n    Pending,\n    Slashed\n}\n\n/// @notice Struct for storing dispute status of an agent.\n/// @param flag         Dispute flag: None/Pending/Slashed.\n/// @param openedAt     Timestamp when the latest agent dispute was opened (zero if not opened).\n/// @param resolvedAt   Timestamp when the latest agent dispute was resolved (zero if not resolved).\nstruct DisputeStatus {\n    DisputeFlag flag;\n    uint40 openedAt;\n    uint40 resolvedAt;\n}\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\n/// @notice Struct representing the status of Destination contract.\n/// @param snapRootTime     Timestamp when latest snapshot root was accepted\n/// @param agentRootTime    Timestamp when latest agent root was accepted\n/// @param notaryIndex      Index of Notary who signed the latest agent root\nstruct DestinationStatus {\n    uint40 snapRootTime;\n    uint40 agentRootTime;\n    uint32 notaryIndex;\n}\n\n// ═══════════════════════════════ EXECUTION HUB ═══════════════════════════════\n\n/// @notice Potential statuses of the message in Execution Hub.\n/// - None: there hasn't been a valid attempt to execute the message yet\n/// - Failed: there was a valid attempt to execute the message, but recipient reverted\n/// - Success: there was a valid attempt to execute the message, and recipient did not revert\n/// Note: message can be executed until its status is Success\nenum MessageStatus {\n    None,\n    Failed,\n    Success\n}\n\nlibrary StructureUtils {\n    /// @notice Checks that Agent is Active\n    function verifyActive(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active) {\n            revert AgentNotActive();\n        }\n    }\n\n    /// @notice Checks that Agent is Unstaking\n    function verifyUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Unstaking) {\n            revert AgentNotUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Active or Unstaking\n    function verifyActiveUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active \u0026\u0026 status.flag != AgentFlag.Unstaking) {\n            revert AgentNotActiveNorUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Fraudulent\n    function verifyFraudulent(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Fraudulent) {\n            revert AgentNotFraudulent();\n        }\n    }\n\n    /// @notice Checks that Agent is not Unknown\n    function verifyKnown(AgentStatus memory status) internal pure {\n        if (status.flag == AgentFlag.Unknown) {\n            revert AgentUnknown();\n        }\n    }\n}\n\n// contracts/libs/memory/MemView.sol\n\n/// @dev MemView is an untyped view over a portion of memory to be used instead of `bytes memory`\ntype MemView is uint256;\n\n/// @dev Attach library functions to MemView\nusing MemViewLib for MemView global;\n\n/// @notice Library for operations with the memory views.\n/// Forked from https://github.com/summa-tx/memview-sol with several breaking changes:\n/// - The codebase is ported to Solidity 0.8\n/// - Custom errors are added\n/// - The runtime type checking is replaced with compile-time check provided by User-Defined Value Types\n///   https://docs.soliditylang.org/en/latest/types.html#user-defined-value-types\n/// - uint256 is used as the underlying type for the \"memory view\" instead of bytes29.\n///   It is wrapped into MemView custom type in order not to be confused with actual integers.\n/// - Therefore the \"type\" field is discarded, allowing to allocate 16 bytes for both view location and length\n/// - The documentation is expanded\n/// - Library functions unused by the rest of the codebase are removed\n//  - Very pretty code separators are added :)\nlibrary MemViewLib {\n    /// @notice Stack layout for uint256 (from highest bits to lowest)\n    /// (32 .. 16]      loc     16 bytes    Memory address of underlying bytes\n    /// (16 .. 00]      len     16 bytes    Length of underlying bytes\n\n    // ═══════════════════════════════════════════ BUILDING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Instantiate a new untyped memory view. This should generally not be called directly.\n     * Prefer `ref` wherever possible.\n     * @param loc_          The memory address\n     * @param len_          The length\n     * @return The new view with the specified location and length\n     */\n    function build(uint256 loc_, uint256 len_) internal pure returns (MemView) {\n        uint256 end_ = loc_ + len_;\n        // Make sure that a view is not constructed that points to unallocated memory\n        // as this could be indicative of a buffer overflow attack\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            if gt(end_, mload(0x40)) { end_ := 0 }\n        }\n        if (end_ == 0) {\n            revert UnallocatedMemory();\n        }\n        return _unsafeBuildUnchecked(loc_, len_);\n    }\n\n    /**\n     * @notice Instantiate a memory view from a byte array.\n     * @dev Note that due to Solidity memory representation, it is not possible to\n     * implement a deref, as the `bytes` type stores its len in memory.\n     * @param arr           The byte array\n     * @return The memory view over the provided byte array\n     */\n    function ref(bytes memory arr) internal pure returns (MemView) {\n        uint256 len_ = arr.length;\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 loc_;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // We add 0x20, so that the view starts exactly where the array data starts\n            loc_ := add(arr, 0x20)\n        }\n        return build(loc_, len_);\n    }\n\n    // ════════════════════════════════════════════ CLONING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to the new memory.\n     * @param memView       The memory view\n     * @return arr          The cloned byte array\n     */\n    function clone(MemView memView) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        unchecked {\n            _unsafeCopyTo(memView, ptr + 0x20);\n        }\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 len_ = memView.len();\n        uint256 footprint_ = memView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    /**\n     * @notice Copies all views, joins them into a new bytearray.\n     * @param memViews      The memory views\n     * @return arr          The new byte array with joined data behind the given views\n     */\n    function join(MemView[] memory memViews) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        MemView newView;\n        unchecked {\n            newView = _unsafeJoin(memViews, ptr + 0x20);\n        }\n        uint256 len_ = newView.len();\n        uint256 footprint_ = newView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    // ══════════════════════════════════════════ INSPECTING MEMORY VIEW ═══════════════════════════════════════════════\n\n    /**\n     * @notice Returns the memory address of the underlying bytes.\n     * @param memView       The memory view\n     * @return loc_         The memory address\n     */\n    function loc(MemView memView) internal pure returns (uint256 loc_) {\n        // loc is stored in the highest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u003e\u003e 128;\n    }\n\n    /**\n     * @notice Returns the number of bytes of the view.\n     * @param memView       The memory view\n     * @return len_         The length of the view\n     */\n    function len(MemView memView) internal pure returns (uint256 len_) {\n        // len is stored in the lowest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u0026 type(uint128).max;\n    }\n\n    /**\n     * @notice Returns the endpoint of `memView`.\n     * @param memView       The memory view\n     * @return end_         The endpoint of `memView`\n     */\n    function end(MemView memView) internal pure returns (uint256 end_) {\n        // The endpoint never overflows uint128, let alone uint256, so we could use unchecked math here\n        unchecked {\n            return memView.loc() + memView.len();\n        }\n    }\n\n    /**\n     * @notice Returns the number of memory words this memory view occupies, rounded up.\n     * @param memView       The memory view\n     * @return words_       The number of memory words\n     */\n    function words(MemView memView) internal pure returns (uint256 words_) {\n        // returning ceil(length / 32.0)\n        unchecked {\n            return (memView.len() + 31) \u003e\u003e 5;\n        }\n    }\n\n    /**\n     * @notice Returns the in-memory footprint of a fresh copy of the view.\n     * @param memView       The memory view\n     * @return footprint_   The in-memory footprint of a fresh copy of the view.\n     */\n    function footprint(MemView memView) internal pure returns (uint256 footprint_) {\n        // words() * 32\n        return memView.words() \u003c\u003c 5;\n    }\n\n    // ════════════════════════════════════════════ HASHING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the keccak256 hash of the underlying memory\n     * @param memView       The memory view\n     * @return digest       The keccak256 hash of the underlying memory\n     */\n    function keccak(MemView memView) internal pure returns (bytes32 digest) {\n        uint256 loc_ = memView.loc();\n        uint256 len_ = memView.len();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            digest := keccak256(loc_, len_)\n        }\n    }\n\n    /**\n     * @notice Adds a salt to the keccak256 hash of the underlying data and returns the keccak256 hash of the\n     * resulting data.\n     * @param memView       The memory view\n     * @return digestSalted keccak256(salt, keccak256(memView))\n     */\n    function keccakSalted(MemView memView, bytes32 salt) internal pure returns (bytes32 digestSalted) {\n        return keccak256(bytes.concat(salt, memView.keccak()));\n    }\n\n    // ════════════════════════════════════════════ SLICING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Safe slicing without memory modification.\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the given index\n     */\n    function slice(MemView memView, uint256 index_, uint256 len_) internal pure returns (MemView) {\n        uint256 loc_ = memView.loc();\n        // Ensure it doesn't overrun the view\n        if (loc_ + index_ + len_ \u003e memView.end()) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // loc_ + index_ \u003c= memView.end()\n            return build({loc_: loc_ + index_, len_: len_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing bytes from `index` to end(memView).\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @return The new view for the slice starting from the given index until the initial view endpoint\n     */\n    function sliceFrom(MemView memView, uint256 index_) internal pure returns (MemView) {\n        uint256 len_ = memView.len();\n        // Ensure it doesn't overrun the view\n        if (index_ \u003e len_) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // index_ \u003c= len_ =\u003e memView.loc() + index_ \u003c= memView.loc() + memView.len() == memView.end()\n            return build({loc_: memView.loc() + index_, len_: len_ - index_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the first `len` bytes.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the initial view beginning\n     */\n    function prefix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        return memView.slice({index_: 0, len_: len_});\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the last `len` byte.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length until the initial view endpoint\n     */\n    function postfix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        uint256 viewLen = memView.len();\n        // Ensure it doesn't overrun the view\n        if (len_ \u003e viewLen) {\n            revert ViewOverrun();\n        }\n        // Could do the unchecked math due to the check above\n        uint256 index_;\n        unchecked {\n            index_ = viewLen - len_;\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // len_ \u003c= memView.len() =\u003e memView.loc() \u003c= loc_ \u003c= memView.end()\n            return build({loc_: memView.loc() + viewLen - len_, len_: len_});\n        }\n    }\n\n    // ═══════════════════════════════════════════ INDEXING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Load up to 32 bytes from the view onto the stack.\n     * @dev Returns a bytes32 with only the `bytes_` HIGHEST bytes set.\n     * This can be immediately cast to a smaller fixed-length byte array.\n     * To automatically cast to an integer, use `indexUint`.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return result       The 32 byte result having only `bytes_` highest bytes set\n     */\n    function index(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (bytes32 result) {\n        if (bytes_ == 0) {\n            return bytes32(0);\n        }\n        // Can't load more than 32 bytes to the stack in one go\n        if (bytes_ \u003e 32) {\n            revert IndexedTooMuch();\n        }\n        // The last indexed byte should be within view boundaries\n        if (index_ + bytes_ \u003e memView.len()) {\n            revert ViewOverrun();\n        }\n        uint256 bitLength = bytes_ \u003c\u003c 3; // bytes_ * 8\n        uint256 loc_ = memView.loc();\n        // Get a mask with `bitLength` highest bits set\n        uint256 mask;\n        // 0x800...00 binary representation is 100...00\n        // sar stands for \"signed arithmetic shift\": https://en.wikipedia.org/wiki/Arithmetic_shift\n        // sar(N-1, 100...00) = 11...100..00, with exactly N highest bits set to 1\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            mask := sar(sub(bitLength, 1), 0x8000000000000000000000000000000000000000000000000000000000000000)\n        }\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load a full word using index offset, and apply mask to ignore non-relevant bytes\n            result := and(mload(add(loc_, index_)), mask)\n        }\n    }\n\n    /**\n     * @notice Parse an unsigned integer from the view at `index`.\n     * @dev Requires that the view have \u003e= `bytes_` bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return The unsigned integer\n     */\n    function indexUint(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (uint256) {\n        bytes32 indexedBytes = memView.index(index_, bytes_);\n        // `index()` returns left-aligned `bytes_`, while integers are right-aligned\n        // Shifting here to right-align with the full 32 bytes word: need to shift right `(32 - bytes_)` bytes\n        unchecked {\n            // memView.index() reverts when bytes_ \u003e 32, thus unchecked math\n            return uint256(indexedBytes) \u003e\u003e ((32 - bytes_) \u003c\u003c 3);\n        }\n    }\n\n    /**\n     * @notice Parse an address from the view at `index`.\n     * @dev Requires that the view have \u003e= 20 bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @return The address\n     */\n    function indexAddress(MemView memView, uint256 index_) internal pure returns (address) {\n        // index 20 bytes as `uint160`, and then cast to `address`\n        return address(uint160(memView.indexUint(index_, 20)));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns a memory view over the specified memory location\n    /// without checking if it points to unallocated memory.\n    function _unsafeBuildUnchecked(uint256 loc_, uint256 len_) private pure returns (MemView) {\n        // There is no scenario where loc or len would overflow uint128, so we omit this check.\n        // We use the highest 128 bits to encode the location and the lowest 128 bits to encode the length.\n        return MemView.wrap((loc_ \u003c\u003c 128) | len_);\n    }\n\n    /**\n     * @notice Copy the view to a location, return an unsafe memory reference\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memView       The memory view\n     * @param newLoc        The new location to copy the underlying view data\n     * @return The memory view over the unsafe memory with the copied underlying data\n     */\n    function _unsafeCopyTo(MemView memView, uint256 newLoc) private view returns (MemView) {\n        uint256 len_ = memView.len();\n        uint256 oldLoc = memView.loc();\n\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (newLoc \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        bool res;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // use the identity precompile (0x04) to copy\n            res := staticcall(gas(), 0x04, oldLoc, len_, newLoc, len_)\n        }\n        if (!res) revert PrecompileOutOfGas();\n        return _unsafeBuildUnchecked({loc_: newLoc, len_: len_});\n    }\n\n    /**\n     * @notice Join the views in memory, return an unsafe reference to the memory.\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memViews      The memory views\n     * @return The conjoined view pointing to the new memory\n     */\n    function _unsafeJoin(MemView[] memory memViews, uint256 location) private view returns (MemView) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (location \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        // Copy the views to the specified location one by one, by tracking the amount of copied bytes so far\n        uint256 offset = 0;\n        for (uint256 i = 0; i \u003c memViews.length;) {\n            MemView memView = memViews[i];\n            // We can use the unchecked math here as location + sum(view.length) will never overflow uint256\n            unchecked {\n                _unsafeCopyTo(memView, location + offset);\n                offset += memView.len();\n                ++i;\n            }\n        }\n        return _unsafeBuildUnchecked({loc_: location, len_: offset});\n    }\n}\n\n// contracts/libs/merkle/MerkleMath.sol\n\nlibrary MerkleMath {\n    // ═════════════════════════════════════════ BASIC MERKLE CALCULATIONS ═════════════════════════════════════════════\n\n    /**\n     * @notice Calculates the merkle root for the given leaf and merkle proof.\n     * @dev Will revert if proof length exceeds the tree height.\n     * @param index     Index of `leaf` in tree\n     * @param leaf      Leaf of the merkle tree\n     * @param proof     Proof of inclusion of `leaf` in the tree\n     * @param height    Height of the merkle tree\n     * @return root_    Calculated Merkle Root\n     */\n    function proofRoot(uint256 index, bytes32 leaf, bytes32[] memory proof, uint256 height)\n        internal\n        pure\n        returns (bytes32 root_)\n    {\n        // Proof length could not exceed the tree height\n        uint256 proofLen = proof.length;\n        if (proofLen \u003e height) revert TreeHeightTooLow();\n        root_ = leaf;\n        /// @dev Apply unchecked to all ++h operations\n        unchecked {\n            // Go up the tree levels from the leaf following the proof\n            for (uint256 h = 0; h \u003c proofLen; ++h) {\n                // Get a sibling node on current level: this is proof[h]\n                root_ = getParent(root_, proof[h], index, h);\n            }\n            // Go up to the root: the remaining siblings are EMPTY\n            for (uint256 h = proofLen; h \u003c height; ++h) {\n                root_ = getParent(root_, bytes32(0), index, h);\n            }\n        }\n    }\n\n    /**\n     * @notice Calculates the parent of a node on the path from one of the leafs to root.\n     * @param node          Node on a path from tree leaf to root\n     * @param sibling       Sibling for a given node\n     * @param leafIndex     Index of the tree leaf\n     * @param nodeHeight    \"Level height\" for `node` (ZERO for leafs, ORIGIN_TREE_HEIGHT for root)\n     */\n    function getParent(bytes32 node, bytes32 sibling, uint256 leafIndex, uint256 nodeHeight)\n        internal\n        pure\n        returns (bytes32 parent)\n    {\n        // Index for `node` on its \"tree level\" is (leafIndex / 2**height)\n        // \"Left child\" has even index, \"right child\" has odd index\n        if ((leafIndex \u003e\u003e nodeHeight) \u0026 1 == 0) {\n            // Left child\n            return getParent(node, sibling);\n        } else {\n            // Right child\n            return getParent(sibling, node);\n        }\n    }\n\n    /// @notice Calculates the parent of tow nodes in the merkle tree.\n    /// @dev We use implementation with H(0,0) = 0\n    /// This makes EVERY empty node in the tree equal to ZERO,\n    /// saving us from storing H(0,0), H(H(0,0), H(0, 0)), and so on\n    /// @param leftChild    Left child of the calculated node\n    /// @param rightChild   Right child of the calculated node\n    /// @return parent      Value for the node having above mentioned children\n    function getParent(bytes32 leftChild, bytes32 rightChild) internal pure returns (bytes32 parent) {\n        if (leftChild == bytes32(0) \u0026\u0026 rightChild == bytes32(0)) {\n            return 0;\n        } else {\n            return keccak256(bytes.concat(leftChild, rightChild));\n        }\n    }\n\n    // ════════════════════════════════ ROOT/PROOF CALCULATION FOR A LIST OF LEAFS ═════════════════════════════════════\n\n    /**\n     * @notice Calculates merkle root for a list of given leafs.\n     * Merkle Tree is constructed by padding the list with ZERO values for leafs until list length is `2**height`.\n     * Merkle Root is calculated for the constructed tree, and then saved in `leafs[0]`.\n     * \u003e Note:\n     * \u003e - `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * \u003e - Caller is expected not to reuse `hashes` list after the call, and only use `leafs[0]` value,\n     * which is guaranteed to contain the calculated merkle root.\n     * \u003e - root is calculated using the `H(0,0) = 0` Merkle Tree implementation. See MerkleTree.sol for details.\n     * @dev Amount of leaves should be at most `2**height`\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param height    Height of the Merkle Tree to construct\n     */\n    function calculateRoot(bytes32[] memory hashes, uint256 height) internal pure {\n        uint256 levelLength = hashes.length;\n        // Amount of hashes could not exceed amount of leafs in tree with the given height\n        if (levelLength \u003e (1 \u003c\u003c height)) revert TreeHeightTooLow();\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\": the amount of iterations for the for loop above.\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n            }\n        }\n    }\n\n    /**\n     * @notice Generates a proof of inclusion of a leaf in the list. If the requested index is outside\n     * of the list range, generates a proof of inclusion for an empty leaf (proof of non-inclusion).\n     * The Merkle Tree is constructed by padding the list with ZERO values until list length is a power of two\n     * __AND__ index is in the extended list range. For example:\n     *  - `hashes.length == 6` and `0 \u003c= index \u003c= 7` will \"extend\" the list to 8 entries.\n     *  - `hashes.length == 6` and `7 \u003c index \u003c= 15` will \"extend\" the list to 16 entries.\n     * \u003e Note: `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * Caller is expected not to reuse `hashes` list after the call.\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param index     Leaf index to generate the proof for\n     * @return proof    Generated merkle proof\n     */\n    function calculateProof(bytes32[] memory hashes, uint256 index) internal pure returns (bytes32[] memory proof) {\n        // Use only meaningful values for the shortened proof\n        // Check if index is within the list range (we want to generates proofs for outside leafs as well)\n        uint256 height = getHeight(index \u003c hashes.length ? hashes.length : (index + 1));\n        proof = new bytes32[](height);\n        uint256 levelLength = hashes.length;\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Use sibling for the merkle proof; `index^1` is index of our sibling\n                proof[h] = (index ^ 1 \u003c levelLength) ? hashes[index ^ 1] : bytes32(0);\n\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\"\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n                // Traverse to parent node\n                index \u003e\u003e= 1;\n            }\n        }\n    }\n\n    /// @notice Returns the height of the tree having a given amount of leafs.\n    function getHeight(uint256 leafs) internal pure returns (uint256 height) {\n        uint256 amount = 1;\n        while (amount \u003c leafs) {\n            unchecked {\n                ++height;\n            }\n            amount \u003c\u003c= 1;\n        }\n    }\n}\n\n// contracts/libs/stack/GasData.sol\n\n/// GasData in encoded data with \"basic information about gas prices\" for some chain.\ntype GasData is uint96;\n\nusing GasDataLib for GasData global;\n\n/// ChainGas is encoded data with given chain's \"basic information about gas prices\".\ntype ChainGas is uint128;\n\nusing GasDataLib for ChainGas global;\n\n/// Library for encoding and decoding GasData and ChainGas structs.\n/// # GasData\n/// `GasData` is a struct to store the \"basic information about gas prices\", that could\n/// be later used to approximate the cost of a message execution, and thus derive the\n/// minimal tip values for sending a message to the chain.\n/// \u003e - `GasData` is supposed to be cached by `GasOracle` contract, allowing to store the\n/// \u003e approximates instead of the exact values, and thus save on storage costs.\n/// \u003e - For instance, if `GasOracle` only updates the values on +- 10% change, having an\n/// \u003e 0.4% error on the approximates would be acceptable.\n/// `GasData` is supposed to be included in the Origin's state, which are synced across\n/// chains using Agent-signed snapshots and attestations.\n/// ## GasData stack layout (from highest bits to lowest)\n///\n/// | Position   | Field        | Type   | Bytes | Description                                         |\n/// | ---------- | ------------ | ------ | ----- | --------------------------------------------------- |\n/// | (012..010] | gasPrice     | uint16 | 2     | Gas price for the chain (in Wei per gas unit)       |\n/// | (010..008] | dataPrice    | uint16 | 2     | Calldata price (in Wei per byte of content)         |\n/// | (008..006] | execBuffer   | uint16 | 2     | Tx fee safety buffer for message execution (in Wei) |\n/// | (006..004] | amortAttCost | uint16 | 2     | Amortized cost for attestation submission (in Wei)  |\n/// | (004..002] | etherPrice   | uint16 | 2     | Chain's Ether Price / Mainnet Ether Price (in BWAD) |\n/// | (002..000] | markup       | uint16 | 2     | Markup for the message execution (in BWAD)          |\n/// \u003e See Number.sol for more details on `Number` type and BWAD (binary WAD) math.\n///\n/// ## ChainGas stack layout (from highest bits to lowest)\n///\n/// | Position   | Field   | Type   | Bytes | Description      |\n/// | ---------- | ------- | ------ | ----- | ---------------- |\n/// | (016..004] | gasData | uint96 | 12    | Chain's gas data |\n/// | (004..000] | domain  | uint32 | 4     | Chain's domain   |\nlibrary GasDataLib {\n    /// @dev Amount of bits to shift to gasPrice field\n    uint96 private constant SHIFT_GAS_PRICE = 10 * 8;\n    /// @dev Amount of bits to shift to dataPrice field\n    uint96 private constant SHIFT_DATA_PRICE = 8 * 8;\n    /// @dev Amount of bits to shift to execBuffer field\n    uint96 private constant SHIFT_EXEC_BUFFER = 6 * 8;\n    /// @dev Amount of bits to shift to amortAttCost field\n    uint96 private constant SHIFT_AMORT_ATT_COST = 4 * 8;\n    /// @dev Amount of bits to shift to etherPrice field\n    uint96 private constant SHIFT_ETHER_PRICE = 2 * 8;\n\n    /// @dev Amount of bits to shift to gasData field\n    uint128 private constant SHIFT_GAS_DATA = 4 * 8;\n\n    // ═════════════════════════════════════════════════ GAS DATA ══════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded GasData struct with the given fields.\n    /// @param gasPrice_        Gas price for the chain (in Wei per gas unit)\n    /// @param dataPrice_       Calldata price (in Wei per byte of content)\n    /// @param execBuffer_      Tx fee safety buffer for message execution (in Wei)\n    /// @param amortAttCost_    Amortized cost for attestation submission (in Wei)\n    /// @param etherPrice_      Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n    /// @param markup_          Markup for the message execution (in BWAD)\n    function encodeGasData(\n        Number gasPrice_,\n        Number dataPrice_,\n        Number execBuffer_,\n        Number amortAttCost_,\n        Number etherPrice_,\n        Number markup_\n    ) internal pure returns (GasData) {\n        // Number type wraps uint16, so could safely be casted to uint96\n        // forgefmt: disable-next-item\n        return GasData.wrap(\n            uint96(Number.unwrap(gasPrice_)) \u003c\u003c SHIFT_GAS_PRICE |\n            uint96(Number.unwrap(dataPrice_)) \u003c\u003c SHIFT_DATA_PRICE |\n            uint96(Number.unwrap(execBuffer_)) \u003c\u003c SHIFT_EXEC_BUFFER |\n            uint96(Number.unwrap(amortAttCost_)) \u003c\u003c SHIFT_AMORT_ATT_COST |\n            uint96(Number.unwrap(etherPrice_)) \u003c\u003c SHIFT_ETHER_PRICE |\n            uint96(Number.unwrap(markup_))\n        );\n    }\n\n    /// @notice Wraps padded uint256 value into GasData struct.\n    function wrapGasData(uint256 paddedGasData) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(paddedGasData));\n    }\n\n    /// @notice Returns the gas price, in Wei per gas unit.\n    function gasPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_GAS_PRICE));\n    }\n\n    /// @notice Returns the calldata price, in Wei per byte of content.\n    function dataPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_DATA_PRICE));\n    }\n\n    /// @notice Returns the tx fee safety buffer for message execution, in Wei.\n    function execBuffer(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_EXEC_BUFFER));\n    }\n\n    /// @notice Returns the amortized cost for attestation submission, in Wei.\n    function amortAttCost(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_AMORT_ATT_COST));\n    }\n\n    /// @notice Returns the ratio of Chain's Ether Price / Mainnet Ether Price, in BWAD math.\n    function etherPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_ETHER_PRICE));\n    }\n\n    /// @notice Returns the markup for the message execution, in BWAD math.\n    function markup(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data)));\n    }\n\n    // ════════════════════════════════════════════════ CHAIN DATA ═════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded ChainGas struct with the given fields.\n    /// @param gasData_ Chain's gas data\n    /// @param domain_  Chain's domain\n    function encodeChainGas(GasData gasData_, uint32 domain_) internal pure returns (ChainGas) {\n        // GasData type wraps uint96, so could safely be casted to uint128\n        return ChainGas.wrap(uint128(GasData.unwrap(gasData_)) \u003c\u003c SHIFT_GAS_DATA | uint128(domain_));\n    }\n\n    /// @notice Wraps padded uint256 value into ChainGas struct.\n    function wrapChainGas(uint256 paddedChainGas) internal pure returns (ChainGas) {\n        // Casting to uint128 will truncate the highest bits, which is the behavior we want\n        return ChainGas.wrap(uint128(paddedChainGas));\n    }\n\n    /// @notice Returns the chain's gas data.\n    function gasData(ChainGas data) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(ChainGas.unwrap(data) \u003e\u003e SHIFT_GAS_DATA));\n    }\n\n    /// @notice Returns the chain's domain.\n    function domain(ChainGas data) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(ChainGas.unwrap(data));\n    }\n\n    /// @notice Returns the hash for the list of ChainGas structs.\n    function snapGasHash(ChainGas[] memory snapGas) internal pure returns (bytes32 snapGasHash_) {\n        // Use assembly to calculate the hash of the array without copying it\n        // ChainGas takes a single word of storage, thus ChainGas[] is stored in the following way:\n        // 0x00: length of the array, in words\n        // 0x20: first ChainGas struct\n        // 0x40: second ChainGas struct\n        // And so on...\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Find the location where the array data starts, we add 0x20 to skip the length field\n            let loc := add(snapGas, 0x20)\n            // Load the length of the array (in words).\n            // Shifting left 5 bits is equivalent to multiplying by 32: this converts from words to bytes.\n            let len := shl(5, mload(snapGas))\n            // Calculate the hash of the array\n            snapGasHash_ := keccak256(loc, len)\n        }\n    }\n}\n\n// contracts/libs/stack/Header.sol\n\n/// Header is encoded data with \"general routing information\".\ntype Header is uint136;\n\nusing HeaderLib for Header global;\n\n/// Types of messages supported by Origin-Destination\n/// - Base: message sent by protocol user, contains tips\n/// - Manager: message sent between AgentManager contracts located on different chains, no tips\nenum MessageFlag {\n    Base,\n    Manager\n}\n\nusing HeaderLib for MessageFlag global;\n\n/// Library for formatting _the header part_ of _the messages used by Origin and Destination_.\n/// - Header represents general information for routing a Message for Origin and Destination.\n/// - Header occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n///\n/// # Header stack layout (from highest bits to lowest)\n///\n/// | Position   | Field            | Type   | Bytes | Description                             |\n/// | ---------- | ---------------- | ------ | ----- | --------------------------------------- |\n/// | (017..016] | flag             | uint8  | 1     | Flag specifying the type of message     |\n/// | (016..012] | origin           | uint32 | 4     | Domain where message originated         |\n/// | (012..008] | nonce            | uint32 | 4     | Message nonce on the origin domain      |\n/// | (008..004] | destination      | uint32 | 4     | Domain where message will be executed   |\n/// | (004..000] | optimisticPeriod | uint32 | 4     | Optimistic period that will be enforced |\nlibrary HeaderLib {\n    /// @dev Amount of bits to shift to flag field\n    uint136 private constant SHIFT_FLAG = 16 * 8;\n    /// @dev Amount of bits to shift to origin field\n    uint136 private constant SHIFT_ORIGIN = 12 * 8;\n    /// @dev Amount of bits to shift to nonce field\n    uint136 private constant SHIFT_NONCE = 8 * 8;\n    /// @dev Amount of bits to shift to destination field\n    uint136 private constant SHIFT_DESTINATION = 4 * 8;\n\n    /// @notice Returns an encoded header with provided fields\n    /// @param origin_              Domain of origin chain\n    /// @param nonce_               Message nonce on origin chain\n    /// @param destination_         Domain of destination chain\n    /// @param optimisticPeriod_    Optimistic period for message execution\n    function encodeHeader(\n        MessageFlag flag_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint32 destination_,\n        uint32 optimisticPeriod_\n    ) internal pure returns (Header) {\n        // All casts below are upcasts, so they are safe\n        // forgefmt: disable-next-item\n        return Header.wrap(\n            uint136(uint8(flag_)) \u003c\u003c SHIFT_FLAG |\n            uint136(origin_) \u003c\u003c SHIFT_ORIGIN |\n            uint136(nonce_) \u003c\u003c SHIFT_NONCE |\n            uint136(destination_) \u003c\u003c SHIFT_DESTINATION |\n            uint136(optimisticPeriod_)\n        );\n    }\n\n    /// @notice Checks that the header is a valid encoded header.\n    function isHeader(uint256 paddedHeader) internal pure returns (bool) {\n        // Check that flag is within range\n        return _flag(paddedHeader) \u003c= uint8(type(MessageFlag).max);\n    }\n\n    /// @notice Wraps the padded encoded request into a Header-typed value.\n    /// @dev The \"padded\" header is simply an encoded header casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded headers\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedHeader) internal pure returns (Header) {\n        // Check that flag is within range\n        if (!isHeader(paddedHeader)) revert FlagOutOfRange();\n        // Casting to uint136 will truncate the highest bits, which is the behavior we want\n        return Header.wrap(uint136(paddedHeader));\n    }\n\n    /// @notice Returns header's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Header header) internal pure returns (bytes32 hashedHeader) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store header in scratch space\n            mstore(0, header)\n            // Compute hash of header padded to 32 bytes\n            hashedHeader := keccak256(0, 32)\n        }\n    }\n\n    // ══════════════════════════════════════════════ HEADER SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns header's flag field\n    function flag(Header header) internal pure returns (MessageFlag) {\n        // We check that flag is within range when wrapping the header, so this cast is safe\n        return MessageFlag(_flag(Header.unwrap(header)));\n    }\n\n    /// @notice Returns header's origin field\n    function origin(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_ORIGIN);\n    }\n\n    /// @notice Returns header's nonce field\n    function nonce(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_NONCE);\n    }\n\n    /// @notice Returns header's destination field\n    function destination(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_DESTINATION);\n    }\n\n    /// @notice Returns header's optimistic seconds field\n    function optimisticPeriod(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns header's flag field without casting to MessageFlag\n    function _flag(uint256 paddedHeader) private pure returns (uint8) {\n        // Casting to uint8 will truncate the highest bits, which is the behavior we want\n        return uint8(paddedHeader \u003e\u003e SHIFT_FLAG);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n     * constructor.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall \u0026\u0026 _initialized \u003c 1) || (!AddressUpgradeable.isContract(address(this)) \u0026\u0026 _initialized == 1),\n            \"Initializable: contract is already initialized\"\n        );\n        _initialized = 1;\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: setting the version to 255 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing \u0026\u0026 _initialized \u003c version, \"Initializable: contract is already initialized\");\n        _initialized = version;\n        _initializing = true;\n        _;\n        _initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        require(_initializing, \"Initializable: contract is not initializing\");\n        _;\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized != type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint8) {\n        return _initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _initializing;\n    }\n}\n\n// contracts/interfaces/IAgentManager.sol\n\ninterface IAgentManager {\n    /**\n     * @notice Allows Inbox to open a Dispute between a Guard and a Notary, if they are both not in Dispute already.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Guard or Notary is already in Dispute.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Allows Inbox to slash an agent, if their fraud was proven.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Domain doesn't match the saved agent domain.\n     * @param domain    Domain where the Agent is active\n     * @param agent     Address of the Agent\n     * @param prover    Address that initially provided fraud proof\n     */\n    function slashAgent(uint32 domain, address agent, address prover) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest known root of the Agent Merkle Tree.\n     */\n    function agentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns the number of opened Disputes.\n     * @dev This includes the Disputes that have been resolved already.\n     */\n    function getDisputesAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns information about the dispute with the given index.\n     * @dev Will revert if dispute with given index hasn't been opened yet.\n     * @param index             Dispute index\n     * @return guard            Address of the Guard in the Dispute\n     * @return notary           Address of the Notary in the Dispute\n     * @return slashedAgent     Address of the Agent who was slashed when Dispute was resolved\n     * @return fraudProver      Address who provided fraud proof to resolve the Dispute\n     * @return reportPayload    Raw payload with report data that led to the Dispute\n     * @return reportSignature  Guard signature for the report payload\n     */\n    function getDispute(uint256 index)\n        external\n        view\n        returns (\n            address guard,\n            address notary,\n            address slashedAgent,\n            address fraudProver,\n            bytes memory reportPayload,\n            bytes memory reportSignature\n        );\n\n    /**\n     * @notice Returns the current Dispute status of a given agent. See Structures.sol for details.\n     * @dev Every returned value will be set to zero if agent was not slashed and is not in Dispute.\n     * `rival` and `disputePtr` will be set to zero if the agent was slashed without being in Dispute.\n     * @param agent         Agent address\n     * @return flag         Flag describing the current Dispute status for the agent: None/Pending/Slashed\n     * @return rival        Address of the rival agent in the Dispute\n     * @return fraudProver  Address who provided fraud proof to resolve the Dispute\n     * @return disputePtr   Index of the opened Dispute PLUS ONE. Zero if agent is not in Dispute.\n     */\n    function disputeStatus(address agent)\n        external\n        view\n        returns (DisputeFlag flag, address rival, address fraudProver, uint256 disputePtr);\n}\n\n// contracts/interfaces/IAgentSecured.sol\n\ninterface IAgentSecured {\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * between a Guard and a Notary has been opened.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * has been resolved due to one of the agents being slashed.\n     * \u003e `rivalIndex` will be ZERO, if the slashed agent was not in the Dispute.\n     * @param slashedIndex  Index of the slashed agent in the Agent Merkle Tree\n     * @param rivalIndex    Index of the their Dispute Rival in the Agent Merkle Tree\n     */\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the address of the local AgentManager contract, which is treated as\n     * the \"source of truth\" for agent statuses.\n     */\n    function agentManager() external view returns (address);\n\n    /**\n     * @notice Returns the address of the local Inbox contract, which is treated as\n     * the \"source of truth\" for agent-signed statements.\n     * @dev Inbox passes verified agent statements to `IAgentSecured` contract.\n     */\n    function inbox() external view returns (address);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns (flag, openedAt, resolvedAt) that describes the latest status of\n     * the latest dispute for an agent with a given index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param agentIndex    Agent index in the Agent Merkle Tree\n     * @return              Latest dispute status for the given agent: (flag, openedAt, resolvedAt)\n     */\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory);\n}\n\n// contracts/libs/memory/ByteString.sol\n\n/// @dev CallData is a memory view over the payload to be used for an external call, i.e.\n/// recipient.call(callData). Its length is always (4 + 32 * N) bytes:\n/// - First 4 bytes represent the function selector.\n/// - 32 * N bytes represent N words that function arguments occupy.\ntype CallData is uint256;\n\n/// @dev Attach library functions to CallData\nusing ByteString for CallData global;\n\n/// @dev Signature is a memory view over a \"65 bytes\" array representing a ECDSA signature.\ntype Signature is uint256;\n\n/// @dev Attach library functions to Signature\nusing ByteString for Signature global;\n\nlibrary ByteString {\n    using MemViewLib for bytes;\n\n    /**\n     * @dev non-compact ECDSA signatures are enforced as of OZ 4.7.3\n     *\n     *      Signature payload memory layout\n     * [000 .. 032) r   bytes32 32 bytes\n     * [032 .. 064) s   bytes32 32 bytes\n     * [064 .. 065) v   uint8    1 byte\n     */\n    uint256 internal constant SIGNATURE_LENGTH = 65;\n    uint256 private constant OFFSET_R = 0;\n    uint256 private constant OFFSET_S = 32;\n    uint256 private constant OFFSET_V = 64;\n\n    /**\n     * @dev Calldata memory layout\n     * [000 .. 004) selector    bytes4  4 bytes\n     *      Optional: N function arguments\n     * [004 .. 036) arg1        bytes32 32 bytes\n     *      ..\n     * [AAA .. END) argN        bytes32 32 bytes\n     */\n    uint256 internal constant SELECTOR_LENGTH = 4;\n    uint256 private constant OFFSET_SELECTOR = 0;\n    uint256 private constant OFFSET_ARGUMENTS = SELECTOR_LENGTH;\n\n    // ═════════════════════════════════════════════════ SIGNATURE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the signature payload from the given values.\n     * @dev Using ByteString.formatSignature({r: r, s: s, v: v}) will make sure\n     * that params are given in the right order.\n     */\n    function formatSignature(bytes32 r, bytes32 s, uint8 v) internal pure returns (bytes memory) {\n        return abi.encodePacked(r, s, v);\n    }\n\n    /**\n     * @notice Returns a Signature view over for the given payload.\n     * @dev Will revert if the payload is not a signature.\n     */\n    function castToSignature(bytes memory payload) internal pure returns (Signature) {\n        return castToSignature(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Signature view.\n     * @dev Will revert if the memory view is not over a signature.\n     */\n    function castToSignature(MemView memView) internal pure returns (Signature) {\n        if (!isSignature(memView)) revert UnformattedSignature();\n        return Signature.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a signature\n     */\n    function isSignature(MemView memView) internal pure returns (bool) {\n        return memView.len() == SIGNATURE_LENGTH;\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Signature signature) internal pure returns (MemView) {\n        return MemView.wrap(Signature.unwrap(signature));\n    }\n\n    // ═════════════════════════════════════════════ SIGNATURE SLICING ═════════════════════════════════════════════════\n\n    /// @notice Unpacks signature payload into (r, s, v) parameters.\n    /// @dev Make sure to verify signature length with isSignature() beforehand.\n    function toRSV(Signature signature) internal pure returns (bytes32 r, bytes32 s, uint8 v) {\n        // Get the underlying memory view\n        MemView memView = unwrap(signature);\n        r = memView.index({index_: OFFSET_R, bytes_: 32});\n        s = memView.index({index_: OFFSET_S, bytes_: 32});\n        // Can be safely casted to uint8, since we index a single byte\n        v = uint8(memView.indexUint({index_: OFFSET_V, bytes_: 1}));\n    }\n\n    // ═════════════════════════════════════════════════ CALLDATA ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the calldata with the modified arguments:\n     * the existing arguments are prepended with the arguments from the prefix.\n     * @dev Given:\n     *  - `calldata = abi.encodeWithSelector(foo.selector, d, e);`\n     *  - `prefix = abi.encode(a, b, c);`\n     *  - `a`, `b`, `c` are arguments of static type (i.e. not dynamically sized ones)\n     *      Then:\n     *  - Function will return abi.encodeWithSelector(foo.selector, a, c, c, d, e)\n     *  - Returned calldata will trigger `foo(a, b, c, d, e)` when used for a contract call.\n     * Note: for clarification as to what types are considered static, see\n     * https://docs.soliditylang.org/en/latest/abi-spec.html#formal-specification-of-the-encoding\n     * @param callData  Calldata that needs to be modified\n     * @param prefix    ABI-encoded arguments to use as the first arguments in the new calldata\n     * @return Modified calldata having prefix as the first arguments.\n     */\n    function addPrefix(CallData callData, bytes memory prefix) internal view returns (bytes memory) {\n        // Prefix should occupy a whole amount of words in memory\n        if (!_fullWords(prefix.length)) revert UnformattedCallDataPrefix();\n        MemView[] memory views = new MemView[](3);\n        // Use payload's function selector\n        views[0] = abi.encodePacked(callData.callSelector()).ref();\n        // Use prefix as the first arguments\n        views[1] = prefix.ref();\n        // Use payload's remaining arguments\n        views[2] = callData.arguments();\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a CallData view over for the given payload.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(bytes memory payload) internal pure returns (CallData) {\n        return castToCallData(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a CallData view.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(MemView memView) internal pure returns (CallData) {\n        if (!isCallData(memView)) revert UnformattedCallData();\n        return CallData.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a valid calldata, i.e.\n     * a function selector, followed by arbitrary amount of arguments.\n     */\n    function isCallData(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Calldata should at least have a function selector\n        if (length \u003c SELECTOR_LENGTH) return false;\n        // The remainder of the calldata should be exactly N memory words (N \u003e= 0)\n        return _fullWords(length - SELECTOR_LENGTH);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(CallData callData) internal pure returns (MemView) {\n        return MemView.wrap(CallData.unwrap(callData));\n    }\n\n    /// @notice Returns callData's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(CallData callData) internal pure returns (bytes32) {\n        return callData.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ CALLDATA SLICING ══════════════════════════════════════════════════\n\n    /**\n     * @notice Returns amount of memory words (32 byte chunks) the function arguments\n     * occupy in the calldata.\n     * @dev This might differ from amount of arguments supplied, if any of the arguments\n     * occupies more than one memory slot. It is true, however, that argument part of the payload\n     * occupies exactly N words, even for dynamic types like `bytes`\n     */\n    function argumentWords(CallData callData) internal pure returns (uint256) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        // Equivalent of (length - SELECTOR_LENGTH) / 32\n        return (memView.len() - SELECTOR_LENGTH) \u003e\u003e 5;\n    }\n\n    /// @notice Returns selector for the provided calldata.\n    function callSelector(CallData callData) internal pure returns (bytes4) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return bytes4(memView.index({index_: OFFSET_SELECTOR, bytes_: SELECTOR_LENGTH}));\n    }\n\n    /// @notice Returns abi encoded arguments for the provided calldata.\n    function arguments(CallData callData) internal pure returns (MemView) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return memView.sliceFrom({index_: OFFSET_ARGUMENTS});\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if length is full amount of memory words (32 bytes).\n    function _fullWords(uint256 length) internal pure returns (bool) {\n        // The equivalent of length % 32 == 0\n        return length \u0026 31 == 0;\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n    function __Context_init() internal onlyInitializing {\n    }\n\n    function __Context_init_unchained() internal onlyInitializing {\n    }\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[50] private __gap;\n}\n\n// contracts/libs/merkle/MerkleTree.sol\n\n/// `BaseTree` is a struct representing incremental merkle tree.\n/// - Contains only the current branch.\n/// - The number of inserted leaves is stored externally, and is later supplied for tree operations.\n/// - Has a fixed height of `ORIGIN_TREE_HEIGHT`.\n/// - Can store up to `2 ** ORIGIN_TREE_HEIGHT - 1` leaves.\n/// \u003e Note: the hash function for the tree `H(x, y)` is defined as:\n/// \u003e - `H(0,0) = 0`\n/// \u003e - `H(x,y) = keccak256(x, y), when (x != 0 || y != 0)`\n/// ## Invariant for leafs\n/// - The leftmost empty leaf has `index == count`, where `count` is the amount of the inserted leafs so far.\n/// - Value for any empty leaf or node is bytes32(0).\n/// ## Invariant for current branch\n/// `branch[i]` is always the value of a node on the i-th level.\n/// Levels are numbered from leafs to root: `0 .. ORIGIN_TREE_HEIGHT`.\n/// `branch[i]` stores the value for the node, such that:\n//  - The node is a \"left child\" (e.g. has an even index).\n/// - The node must have two non-empty children.\n/// - Out of all level's \"left child\" nodes with \"non-empty children\",\n/// the one with the biggest index (the rightmost one) is stored as `branch[i]`.\n/// \u003e __`branch` could be used to form a proof of inclusion for the first empty leaf (`index == count`).__\n/// _Here is how:_\n/// - Let's walk along the path from the \"first empty leaf\" to the root.\n/// - i-th bit of the \"first empty leaf\" index (which is equal to `count`) determines if the path's node\n/// for this i-th level is a \"left child\" or a \"right child\".\n/// - i-th bit in `count` is 0 → we are the left child on this level → sibling is the right child\n/// that does not exist yet → `proof[i] = bytes32(0)`.\n/// - i-th bit in `count` is 1 → we are the right child on this level → sibling is the left child\n/// sibling is the rightmost \"left child\" node on the level → `proof[i] = branch[i]`.\n/// \u003e Therefore `proof[i] = (count \u0026 (1 \u003c\u003c i)) == 0 ? bytes32(0) : branch[i])`\nstruct BaseTree {\n    bytes32[ORIGIN_TREE_HEIGHT] branch;\n}\n\nusing MerkleTree for BaseTree global;\n\n/// `HistoricalTree` is an incremental merkle tree keeping track of its historical merkle roots.\n/// \u003e - `roots[N]` is the root of the tree after `N` leafs were inserted\n/// \u003e - `roots[0] == bytes32(0)`\n/// @param tree     Incremental merkle tree\n/// @param roots    Historical merkle roots of the tree\nstruct HistoricalTree {\n    BaseTree tree;\n    bytes32[] roots;\n}\n\nusing MerkleTree for HistoricalTree global;\n\n/// `DynamicTree` is a struct representing a Merkle Tree with `2**AGENT_TREE_HEIGHT` leaves.\n/// - A single operation is available: update value for leaf with an arbitrary index (which might be a non-empty leaf).\n/// - This is done by requesting the proof of inclusion for the old value, which is used to both\n/// verify the old value, and calculate the new root.\n/// \u003e Based on Original idea from [ER forum post](https://ethresear.ch/t/efficient-on-chain-dynamic-merkle-tree/11054).\nstruct DynamicTree {\n    bytes32 root;\n}\n\nusing MerkleTree for DynamicTree global;\n\n/// MerkleTree is work based on Nomad's Merkle.sol, which is used under MIT OR Apache-2.0\n/// [link](https://github.com/nomad-xyz/monorepo/blob/main/packages/contracts-core/contracts/libs/Merkle.sol).\n/// With the following changes:\n/// - Adapted for Solidity 0.8.x.\n/// - Amount of tree leaves stored externally.\n/// - Added thorough documentation.\n/// - `H(0,0) = 0` optimization from [ER forum post](https://ethresear.ch/t/optimizing-sparse-merkle-trees/3751/6).\n/// \u003e Nomad's Merkle.sol is work based on eth2 deposit contract, which is used under CC0-1.0\n///[link](https://github.com/ethereum/deposit_contract/blob/dev/deposit_contract/contracts/validator_registration.v.py).\n/// With the following changes:\n/// \u003e - Implemented in Solidity 0.7.6 (eth2 deposit contract implemented in Vyper).\n/// \u003e - `H() = keccak256()` is used as the hashing function instead of `sha256()`.\nlibrary MerkleTree {\n    /// @dev For root calculation we need at least one empty leaf, thus the minus one in the formula.\n    uint256 internal constant MAX_LEAVES = 2 ** ORIGIN_TREE_HEIGHT - 1;\n\n    // ═════════════════════════════════════════════════ BASE TREE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Inserts `node` into merkle tree\n     * @dev Reverts if tree is full\n     * @param newCount  Amount of inserted leaves in the tree after the insertion (i.e. current + 1)\n     * @param node      Element to insert into tree\n     */\n    function insertBase(BaseTree storage tree, uint256 newCount, bytes32 node) internal {\n        if (newCount \u003e MAX_LEAVES) revert MerkleTreeFull();\n        // We go up the tree following the branch from the empty leaf AFTER the just inserted one.\n        // We stop when we find the first \"right child\" node.\n        // Its sibling is now the rightmost \"left child\" node that has two non-empty children.\n        // Therefore we need to update `tree.branch` value on this level.\n        // One could see that `tree.branch` value on lower and higher levels remain unchanged.\n\n        // Loop invariant: `node` is the current level's value for the branch from JUST INSERTED leaf\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            if ((newCount \u0026 1) == 1) {\n                // Found the first \"right child\" node on the branch from EMPTY leaf\n                // `node` is the value for node on branch from JUST INSERTED leaf\n                // Which in this case is the \"left child\".\n                // We update tree.branch and exit\n                tree.branch[i] = node;\n                return;\n            }\n            // On the branch from EMPTY leaf this is still a \"left child\".\n            // Meaning on branch from JUST INSERTED leaf, `node` is a right child.\n            // We compute value for `node` parent using `tree.branch` invariant:\n            // This is the rightmost \"left child\" node, which would be sibling of `node`.\n            node = MerkleMath.getParent(tree.branch[i], node);\n            // Get the parent index, and go to the next tree level\n            newCount \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n        // As the loop should always end prematurely with the `return` statement,\n        // this code should be unreachable. We assert `false` just to be safe.\n        assert(false);\n    }\n\n    /**\n     * @notice Calculates and returns current root of the merkle tree.\n     * @param count     Current amount of inserted leaves in the tree\n     * @return current  Calculated root of `tree`\n     */\n    function rootBase(BaseTree storage tree, uint256 count) internal view returns (bytes32 current) {\n        // To calculate the root we follow the branch of first EMPTY leaf (index == count)\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            // Check if we are the left or the right child on the current level\n            if ((count \u0026 1) == 1) {\n                // We are the right child. Our sibling is the \"rightmost\" \"left-child\" node\n                // that has two non-empty children → sibling is `tree.branch[i]`\n                current = MerkleMath.getParent(tree.branch[i], current);\n            } else {\n                // We are the left child. Our sibling does not exist yet → sibling is EMPTY\n                current = MerkleMath.getParent(current, bytes32(0));\n            }\n            // Get the parent index, and go to the next tree level\n            count \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    // ══════════════════════════════════════════════ HISTORICAL TREE ══════════════════════════════════════════════════\n\n    /// @notice Initializes the historical roots for the tree by inserting an empty root.\n    // solhint-disable-next-line ordering\n    function initializeRoots(HistoricalTree storage tree) internal returns (bytes32 savedRoot) {\n        // This should only be called once, when the contract is initialized\n        assert(tree.roots.length == 0);\n        // Save root for empty merkle tree: bytes32(0)\n        tree.roots.push(savedRoot);\n    }\n\n    /// @notice Inserts a new leaf into the merkle tree.\n    /// @dev Reverts if tree is full.\n    /// @param node         Element to insert into tree\n    /// @return newRoot     Merkle root after the leaf was inserted\n    function insert(HistoricalTree storage tree, bytes32 node) internal returns (bytes32 newRoot) {\n        // Tree count after the new leaf will be inserted (we store roots[0] as root of empty tree)\n        uint256 newCount = tree.roots.length;\n        tree.tree.insertBase(newCount, node);\n        // Save the new root\n        newRoot = tree.tree.rootBase(newCount);\n        tree.roots.push(newRoot);\n    }\n\n    /// @notice Returns the historical root of the merkle tree.\n    /// @dev Reverts if not enough leafs have been inserted.\n    /// @param count            Amount of leafs in the tree at some point of time\n    /// @return historicalRoot  Merkle root after `count` leafs were inserted\n    function root(HistoricalTree storage tree, uint256 count) internal view returns (bytes32 historicalRoot) {\n        if (count \u003e= tree.roots.length) revert NotEnoughLeafs();\n        return tree.roots[count];\n    }\n\n    // ═══════════════════════════════════════════════ DYNAMIC TREE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Updates the value for the leaf with the given index in the Dynamic Merkle Tree.\n     * @dev Will revert if incorrect proof of inclusion for old value is supplied.\n     * @param tree          Dynamic merkle tree\n     * @param index         Index of the leaf to update\n     * @param oldValue      Previous value of the leaf\n     * @param branch        Proof of inclusion of previous value into the tree\n     * @param newValue      New leaf value to assign\n     * @return newRoot      New value for the Merkle Root after the leaf is updated\n     */\n    function update(\n        DynamicTree storage tree,\n        uint256 index,\n        bytes32 oldValue,\n        bytes32[] memory branch,\n        bytes32 newValue\n    ) internal returns (bytes32 newRoot) {\n        // Check that the old value + proof result in a correct root\n        if (MerkleMath.proofRoot(index, oldValue, branch, AGENT_TREE_HEIGHT) != tree.root) {\n            revert LeafNotProven();\n        }\n        // New root is new value + the same proof (values for sibling nodes are not updated)\n        newRoot = MerkleMath.proofRoot(index, newValue, branch, AGENT_TREE_HEIGHT);\n        // Write the new root\n        tree.root = newRoot;\n    }\n}\n\n// contracts/libs/stack/Tips.sol\n\n/// Tips is encoded data with \"tips paid for sending a base message\".\n/// Note: even though uint256 is also an underlying type for MemView, Tips is stored ON STACK.\ntype Tips is uint256;\n\nusing TipsLib for Tips global;\n\n/// # Tips\n/// Library for formatting _the tips part_ of _the base messages_.\n///\n/// ## How the tips are awarded\n/// Tips are paid for sending a base message, and are split across all the agents that\n/// made the message execution on destination chain possible.\n/// ### Summit tips\n/// Split between:\n///     - Guard posting a snapshot with state ST_G for the origin chain.\n///     - Notary posting a snapshot SN_N using ST_G. This creates attestation A.\n///     - Notary posting a message receipt after it is executed on destination chain.\n/// ### Attestation tips\n/// Paid to:\n///     - Notary posting attestation A to destination chain.\n/// ### Execution tips\n/// Paid to:\n///     - First executor performing a valid execution attempt (correct proofs, optimistic period over),\n///      using attestation A to prove message inclusion on origin chain, whether the recipient reverted or not.\n/// ### Delivery tips.\n/// Paid to:\n///     - Executor who successfully executed the message on destination chain.\n///\n/// ## Tips encoding\n/// - Tips occupy a single storage word, and thus are stored on stack instead of being stored in memory.\n/// - The actual tip values should be determined by multiplying stored values by divided by TIPS_MULTIPLIER=2**32.\n/// - Tips are packed into a single word of storage, while allowing real values up to ~8*10**28 for every tip category.\n/// \u003e The only downside is that the \"real tip values\" are now multiplies of ~4*10**9, which should be fine even for\n/// the chains with the most expensive gas currency.\n/// # Tips stack layout (from highest bits to lowest)\n///\n/// | Position   | Field          | Type   | Bytes | Description                                                |\n/// | ---------- | -------------- | ------ | ----- | ---------------------------------------------------------- |\n/// | (032..024] | summitTip      | uint64 | 8     | Tip for agents interacting with Summit contract            |\n/// | (024..016] | attestationTip | uint64 | 8     | Tip for Notary posting attestation to Destination contract |\n/// | (016..008] | executionTip   | uint64 | 8     | Tip for valid execution attempt on destination chain       |\n/// | (008..000] | deliveryTip    | uint64 | 8     | Tip for successful message delivery on destination chain   |\n\nlibrary TipsLib {\n    using SafeCast for uint256;\n\n    /// @dev Amount of bits to shift to summitTip field\n    uint256 private constant SHIFT_SUMMIT_TIP = 24 * 8;\n    /// @dev Amount of bits to shift to attestationTip field\n    uint256 private constant SHIFT_ATTESTATION_TIP = 16 * 8;\n    /// @dev Amount of bits to shift to executionTip field\n    uint256 private constant SHIFT_EXECUTION_TIP = 8 * 8;\n\n    // ═══════════════════════════════════════════════════ TIPS ════════════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips with the given fields\n    /// @param summitTip_        Tip for agents interacting with Summit contract, divided by TIPS_MULTIPLIER\n    /// @param attestationTip_   Tip for Notary posting attestation to Destination contract, divided by TIPS_MULTIPLIER\n    /// @param executionTip_     Tip for valid execution attempt on destination chain, divided by TIPS_MULTIPLIER\n    /// @param deliveryTip_      Tip for successful message delivery on destination chain, divided by TIPS_MULTIPLIER\n    function encodeTips(uint64 summitTip_, uint64 attestationTip_, uint64 executionTip_, uint64 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // forgefmt: disable-next-item\n        return Tips.wrap(\n            uint256(summitTip_) \u003c\u003c SHIFT_SUMMIT_TIP |\n            uint256(attestationTip_) \u003c\u003c SHIFT_ATTESTATION_TIP |\n            uint256(executionTip_) \u003c\u003c SHIFT_EXECUTION_TIP |\n            uint256(deliveryTip_)\n        );\n    }\n\n    /// @notice Convenience function to encode tips with uint256 values.\n    function encodeTips256(uint256 summitTip_, uint256 attestationTip_, uint256 executionTip_, uint256 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // In practice, the tips amounts are not supposed to be higher than 2**96, and with 32 bits of granularity\n        // using uint64 is enough to store the values. However, we still check for overflow just in case.\n        // TODO: consider using Number type to store the tips values.\n        return encodeTips({\n            summitTip_: (summitTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            attestationTip_: (attestationTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            executionTip_: (executionTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            deliveryTip_: (deliveryTip_ \u003e\u003e TIPS_GRANULARITY).toUint64()\n        });\n    }\n\n    /// @notice Wraps the padded encoded tips into a Tips-typed value.\n    /// @dev There is no actual padding here, as the underlying type is already uint256,\n    /// but we include this function for consistency and to be future-proof, if tips will eventually use anything\n    /// smaller than uint256.\n    function wrapPadded(uint256 paddedTips) internal pure returns (Tips) {\n        return Tips.wrap(paddedTips);\n    }\n\n    /**\n     * @notice Returns a formatted Tips payload specifying empty tips.\n     * @return Formatted tips\n     */\n    function emptyTips() internal pure returns (Tips) {\n        return Tips.wrap(0);\n    }\n\n    /// @notice Returns tips's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Tips tips) internal pure returns (bytes32 hashedTips) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store tips in scratch space\n            mstore(0, tips)\n            // Compute hash of tips padded to 32 bytes\n            hashedTips := keccak256(0, 32)\n        }\n    }\n\n    // ═══════════════════════════════════════════════ TIPS SLICING ════════════════════════════════════════════════════\n\n    /// @notice Returns summitTip field\n    function summitTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_SUMMIT_TIP);\n    }\n\n    /// @notice Returns attestationTip field\n    function attestationTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_ATTESTATION_TIP);\n    }\n\n    /// @notice Returns executionTip field\n    function executionTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_EXECUTION_TIP);\n    }\n\n    /// @notice Returns deliveryTip field\n    function deliveryTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips));\n    }\n\n    // ════════════════════════════════════════════════ TIPS VALUE ═════════════════════════════════════════════════════\n\n    /// @notice Returns total value of the tips payload.\n    /// This is the sum of the encoded values, scaled up by TIPS_MULTIPLIER\n    function value(Tips tips) internal pure returns (uint256 value_) {\n        value_ = uint256(tips.summitTip()) + tips.attestationTip() + tips.executionTip() + tips.deliveryTip();\n        value_ \u003c\u003c= TIPS_GRANULARITY;\n    }\n\n    /// @notice Increases the delivery tip to match the new value.\n    function matchValue(Tips tips, uint256 newValue) internal pure returns (Tips newTips) {\n        uint256 oldValue = tips.value();\n        if (newValue \u003c oldValue) revert TipsValueTooLow();\n        // We want to increase the delivery tip, while keeping the other tips the same\n        unchecked {\n            uint256 delta = (newValue - oldValue) \u003e\u003e TIPS_GRANULARITY;\n            // `delta` fits into uint224, as TIPS_GRANULARITY is 32, so this never overflows uint256.\n            // In practice, this will never overflow uint64 as well, but we still check it just in case.\n            if (delta + tips.deliveryTip() \u003e type(uint64).max) revert TipsOverflow();\n            // Delivery tips occupy lowest 8 bytes, so we can just add delta to the tips value\n            // to effectively increase the delivery tip (knowing that delta fits into uint64).\n            newTips = Tips.wrap(Tips.unwrap(tips) + delta);\n        }\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    function __Ownable_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable_init_unchained() internal onlyInitializing {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n    function __Ownable2Step_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable2Step_init_unchained() internal onlyInitializing {\n    }\n    address private _pendingOwner;\n\n    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Returns the address of the pending owner.\n     */\n    function pendingOwner() public view virtual returns (address) {\n        return _pendingOwner;\n    }\n\n    /**\n     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual override onlyOwner {\n        _pendingOwner = newOwner;\n        emit OwnershipTransferStarted(owner(), newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual override {\n        delete _pendingOwner;\n        super._transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev The new owner accepts the ownership transfer.\n     */\n    function acceptOwnership() public virtual {\n        address sender = _msgSender();\n        require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n        _transferOwnership(sender);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// contracts/libs/memory/State.sol\n\n/// State is a memory view over a formatted state payload.\ntype State is uint256;\n\nusing StateLib for State global;\n\n/// # State\n/// State structure represents the state of Origin contract at some point of time.\n/// - State is structured in a way to track the updates of the Origin Merkle Tree.\n/// - State includes root of the Origin Merkle Tree, origin domain and some additional metadata.\n/// ## Origin Merkle Tree\n/// Hash of every sent message is inserted in the Origin Merkle Tree, which changes\n/// the value of Origin Merkle Root (which is the root for the mentioned tree).\n/// - Origin has a single Merkle Tree for all messages, regardless of their destination domain.\n/// - This leads to Origin state being updated if and only if a message was sent in a block.\n/// - Origin contract is a \"source of truth\" for states: a state is considered \"valid\" in its Origin,\n/// if it matches the state of the Origin contract after the N-th (nonce) message was sent.\n///\n/// # Memory layout of State fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                    |\n/// | ---------- | ----------- | ------- | ----- | ------------------------------ |\n/// | [000..032) | root        | bytes32 | 32    | Root of the Origin Merkle Tree |\n/// | [032..036) | origin      | uint32  | 4     | Domain where Origin is located |\n/// | [036..040) | nonce       | uint32  | 4     | Amount of sent messages        |\n/// | [040..045) | blockNumber | uint40  | 5     | Block of last sent message     |\n/// | [045..050) | timestamp   | uint40  | 5     | Time of last sent message      |\n/// | [050..062) | gasData     | uint96  | 12    | Gas data for the chain         |\n///\n/// @dev State could be used to form a Snapshot to be signed by a Guard or a Notary.\nlibrary StateLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_ROOT = 0;\n    uint256 private constant OFFSET_ORIGIN = 32;\n    uint256 private constant OFFSET_NONCE = 36;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 40;\n    uint256 private constant OFFSET_TIMESTAMP = 45;\n    uint256 private constant OFFSET_GAS_DATA = 50;\n\n    // ═══════════════════════════════════════════════════ STATE ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted State payload with provided fields\n     * @param root_         New merkle root\n     * @param origin_       Domain of Origin's chain\n     * @param nonce_        Nonce of the merkle root\n     * @param blockNumber_  Block number when root was saved in Origin\n     * @param timestamp_    Block timestamp when root was saved in Origin\n     * @param gasData_      Gas data for the chain\n     * @return Formatted state\n     */\n    function formatState(\n        bytes32 root_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_,\n        GasData gasData_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(root_, origin_, nonce_, blockNumber_, timestamp_, gasData_);\n    }\n\n    /**\n     * @notice Returns a State view over the given payload.\n     * @dev Will revert if the payload is not a state.\n     */\n    function castToState(bytes memory payload) internal pure returns (State) {\n        return castToState(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a State view.\n     * @dev Will revert if the memory view is not over a state.\n     */\n    function castToState(MemView memView) internal pure returns (State) {\n        if (!isState(memView)) revert UnformattedState();\n        return State.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted State.\n    function isState(MemView memView) internal pure returns (bool) {\n        return memView.len() == STATE_LENGTH;\n    }\n\n    /// @notice Returns the hash of a State, that could be later signed by a Guard to signal\n    /// that the state is invalid.\n    function hashInvalid(State state) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(stateInvalidSalt, keccak(state))\n        return state.unwrap().keccakSalted(STATE_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(State state) internal pure returns (MemView) {\n        return MemView.wrap(State.unwrap(state));\n    }\n\n    /// @notice Compares two State structures.\n    function equals(State a, State b) internal pure returns (bool) {\n        // Length of a State payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═══════════════════════════════════════════════ STATE HASHING ═══════════════════════════════════════════════════\n\n    /// @notice Returns the hash of the State.\n    /// @dev We are using the Merkle Root of a tree with two leafs (see below) as state hash.\n    function leaf(State state) internal pure returns (bytes32) {\n        (bytes32 leftLeaf_, bytes32 rightLeaf_) = state.subLeafs();\n        // Final hash is the parent of these leafs\n        return keccak256(bytes.concat(leftLeaf_, rightLeaf_));\n    }\n\n    /// @notice Returns \"sub-leafs\" of the State. Hash of these \"sub leafs\" is going to be used\n    /// as a \"state leaf\" in the \"Snapshot Merkle Tree\".\n    /// This enables proving that leftLeaf = (root, origin) was a part of the \"Snapshot Merkle Tree\",\n    /// by combining `rightLeaf` with the remainder of the \"Snapshot Merkle Proof\".\n    function subLeafs(State state) internal pure returns (bytes32 leftLeaf_, bytes32 rightLeaf_) {\n        MemView memView = state.unwrap();\n        // Left leaf is (root, origin)\n        leftLeaf_ = memView.prefix({len_: OFFSET_NONCE}).keccak();\n        // Right leaf is (metadata), or (nonce, blockNumber, timestamp)\n        rightLeaf_ = memView.sliceFrom({index_: OFFSET_NONCE}).keccak();\n    }\n\n    /// @notice Returns the left \"sub-leaf\" of the State.\n    function leftLeaf(bytes32 root_, uint32 origin_) internal pure returns (bytes32) {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(root_, origin_));\n    }\n\n    /// @notice Returns the right \"sub-leaf\" of the State.\n    function rightLeaf(uint32 nonce_, uint40 blockNumber_, uint40 timestamp_, GasData gasData_)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(nonce_, blockNumber_, timestamp_, gasData_));\n    }\n\n    // ═══════════════════════════════════════════════ STATE SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns a historical Merkle root from the Origin contract.\n    function root(State state) internal pure returns (bytes32) {\n        return state.unwrap().index({index_: OFFSET_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns domain of chain where the Origin contract is deployed.\n    function origin(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns nonce of Origin contract at the time, when `root` was the Merkle root.\n    function nonce(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when `root` was saved in Origin.\n    function blockNumber(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when `root` was saved in Origin.\n    /// @dev This is the timestamp according to the origin chain.\n    function timestamp(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n\n    /// @notice Returns gas data for the chain.\n    function gasData(State state) internal pure returns (GasData) {\n        return GasDataLib.wrapGasData(state.unwrap().indexUint({index_: OFFSET_GAS_DATA, bytes_: GAS_DATA_LENGTH}));\n    }\n}\n\n// contracts/libs/memory/BaseMessage.sol\n\n/// BaseMessage is a memory view over the base message supported by Origin-Destination\ntype BaseMessage is uint256;\n\nusing BaseMessageLib for BaseMessage global;\n\n/// BaseMessage structure represents a base message sent via the Origin-Destination contracts.\n/// - It only contains data relevant to the base message, the rest of data is encoded in the message header.\n/// - `sender` and `recipient` for EVM chains are EVM addresses casted to bytes32, while preserving left-alignment.\n/// - `tips` and `request` parameters are specified by a message sender\n/// \u003e Origin will calculate minimum tips for given request and content length, and will reject messages with tips\n/// lower than that.\n///\n/// # Memory layout of BaseMessage fields\n///\n/// | Position   | Field     | Type    | Bytes | Description                            |\n/// | ---------- | --------- | ------- | ----- | -------------------------------------- |\n/// | [000..032) | tips      | uint256 | 32    | Encoded tips paid on origin chain      |\n/// | [032..064) | sender    | bytes32 | 32    | Sender address on origin chain         |\n/// | [064..096) | recipient | bytes32 | 32    | Recipient address on destination chain |\n/// | [096..116) | request   | uint160 | 20    | Encoded request for message execution  |\n/// | [104..AAA) | content   | bytes   | ??    | Content to be passed to recipient      |\nlibrary BaseMessageLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_TIPS = 0;\n    uint256 private constant OFFSET_SENDER = 32;\n    uint256 private constant OFFSET_RECIPIENT = 64;\n    uint256 private constant OFFSET_REQUEST = OFFSET_RECIPIENT + TIPS_LENGTH;\n    uint256 private constant OFFSET_CONTENT = OFFSET_REQUEST + REQUEST_LENGTH;\n\n    // ═══════════════════════════════════════════════ BASE MESSAGE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted BaseMessage payload with provided fields.\n     * @param tips_         Encoded tips information\n     * @param sender_       Sender address on origin chain\n     * @param recipient_    Recipient address on destination chain\n     * @param request_      Encoded request for message execution\n     * @param content_      Raw content to be passed to recipient on destination chain\n     * @return Formatted base message\n     */\n    function formatBaseMessage(Tips tips_, bytes32 sender_, bytes32 recipient_, Request request_, bytes memory content_)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return abi.encodePacked(tips_, sender_, recipient_, request_, content_);\n    }\n\n    /**\n     * @notice Returns a BaseMessage view over the given payload.\n     * @dev Will revert if the payload is not a base message.\n     */\n    function castToBaseMessage(bytes memory payload) internal pure returns (BaseMessage) {\n        return castToBaseMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a BaseMessage view.\n     * @dev Will revert if the memory view is not over a base message payload.\n     */\n    function castToBaseMessage(MemView memView) internal pure returns (BaseMessage) {\n        if (!isBaseMessage(memView)) revert UnformattedBaseMessage();\n        return BaseMessage.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted BaseMessage.\n    function isBaseMessage(MemView memView) internal pure returns (bool) {\n        // Check if sender, recipient, tips fields exist\n        return (memView.len() \u003e= OFFSET_CONTENT);\n        // Content could be empty, so we don't check that\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(BaseMessage baseMessage) internal pure returns (MemView) {\n        return MemView.wrap(BaseMessage.unwrap(baseMessage));\n    }\n\n    /// @notice Returns baseMessage's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        // We hash \"tips\" and \"everything but tips\" to make tips proofs easier to verify\n        return MerkleMath.getParent(baseMessage.tips().leaf(), baseMessage.bodyLeaf());\n    }\n\n    /// @notice Returns hash for the \"everything but tips\" part of the base message.\n    function bodyLeaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_SENDER}).keccak();\n    }\n\n    // ═══════════════════════════════════════════ BASE MESSAGE SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips paid on origin chain.\n    function tips(BaseMessage baseMessage) internal pure returns (Tips) {\n        return TipsLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_TIPS, bytes_: TIPS_LENGTH})));\n    }\n\n    /// @notice Returns sender address on origin chain.\n    function sender(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_SENDER, bytes_: 32});\n    }\n\n    /// @notice Returns recipient address on destination chain.\n    function recipient(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_RECIPIENT, bytes_: 32});\n    }\n\n    /// @notice Returns an encoded request for message execution on destination chain.\n    function request(BaseMessage baseMessage) internal pure returns (Request) {\n        return RequestLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_REQUEST, bytes_: REQUEST_LENGTH})));\n    }\n\n    /// @notice Returns an untyped memory view over the content to be passed to recipient.\n    function content(BaseMessage baseMessage) internal pure returns (MemView) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_CONTENT});\n    }\n}\n\n// contracts/base/MessagingBase.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for all messaging contracts.\n * - Provides context on the local chain's domain.\n * - Provides ownership functionality.\n * - Will be providing pausing functionality when it is implemented.\n */\nabstract contract MessagingBase is MultiCallable, Versioned, Ownable2StepUpgradeable {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @notice Domain of the local chain, set once upon contract creation\n    uint32 public immutable localDomain;\n    // @notice Domain of the Synapse chain, set once upon contract creation\n    uint32 public immutable synapseDomain;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev gap for upgrade safety\n    uint256[50] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    constructor(string memory version_, uint32 synapseDomain_) Versioned(version_) {\n        localDomain = ChainContext.chainId();\n        synapseDomain = synapseDomain_;\n    }\n\n    // TODO: Implement pausing\n\n    /**\n     * @dev Should be impossible to renounce ownership;\n     * we override OpenZeppelin OwnableUpgradeable's\n     * implementation of renounceOwnership to make it a no-op\n     */\n    function renounceOwnership() public override onlyOwner {} //solhint-disable-line no-empty-blocks\n}\n\n// contracts/libs/memory/Message.sol\n\n/// Message is a memory over over a formatted message payload.\ntype Message is uint256;\n\nusing MessageLib for Message global;\n\n/// Library for formatting the various messages supported by Origin and Destination.\n///\n/// # Message memory layout\n///\n/// | Position   | Field  | Type    | Bytes | Description                                             |\n/// | ---------- | ------ | ------- | ----- | ------------------------------------------------------- |\n/// | [000..017) | header | uint136 | 17    | Encoded general routing information for the message     |\n/// | [017..AAA) | body   | bytes   | ??    | Formatted payload (according to flag) with message body |\nlibrary MessageLib {\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MemViewLib for bytes;\n    using HeaderLib for MemView;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_HEADER = 0;\n    uint256 private constant OFFSET_BODY = OFFSET_HEADER + HEADER_LENGTH;\n\n    // ══════════════════════════════════════════════════ MESSAGE ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns formatted message with provided fields.\n     * @param header_   Encoded general routing information for the message\n     * @param body_     Formatted payload (according to flag) with message body\n     * @return Formatted message\n     */\n    function formatMessage(Header header_, bytes memory body_) internal pure returns (bytes memory) {\n        return abi.encodePacked(header_, body_);\n    }\n\n    /**\n     * @notice Returns a Message view over for the given payload.\n     * @dev Will revert if the payload is not a message payload.\n     */\n    function castToMessage(bytes memory payload) internal pure returns (Message) {\n        return castToMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Message view.\n     * @dev Will revert if the memory view is not over a message payload.\n     */\n    function castToMessage(MemView memView) internal pure returns (Message) {\n        if (!isMessage(memView)) revert UnformattedMessage();\n        return Message.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Message.\n     */\n    function isMessage(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Check if headers exist in the payload\n        if (length \u003c OFFSET_BODY) return false;\n        // Check that Header is valid\n        uint256 paddedHeader = _header(memView);\n        if (!HeaderLib.isHeader(paddedHeader)) return false;\n        // Check that body is formatted according to the flag\n        // Only Base/Manager message flags exist\n        if (HeaderLib.wrapPadded(paddedHeader).flag() == MessageFlag.Base) {\n            // Check if body is a formatted base message\n            return _body(memView).isBaseMessage();\n        } else {\n            // Check if body is a formatted calldata for AgentManager call\n            return _body(memView).isCallData();\n        }\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Message message) internal pure returns (MemView) {\n        return MemView.wrap(Message.unwrap(message));\n    }\n\n    /// @notice Returns message's hash: a leaf to be inserted in the Merkle tree.\n    function leaf(Message message) internal pure returns (bytes32) {\n        // We hash header and body separately to make message proofs easier to verify\n        Header header_ = message.header();\n        // Only Base/Manager message flags exist\n        if (header_.flag() == MessageFlag.Base) {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToBaseMessage().leaf());\n        } else {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToCallData().leaf());\n        }\n    }\n\n    // ══════════════════════════════════════════════ MESSAGE SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns message's encoded header field.\n    function header(Message message) internal pure returns (Header) {\n        return HeaderLib.wrapPadded((message.unwrap().indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH})));\n    }\n\n    /// @notice Returns message's body field as an untyped memory view.\n    function body(Message message) internal pure returns (MemView) {\n        MemView memView = message.unwrap();\n        return _body(memView);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns message's padded header without checking that it is a valid header.\n    function _header(MemView memView) private pure returns (uint256) {\n        return memView.indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH});\n    }\n\n    /// @dev Returns an untyped memory view over the body field without checking\n    /// if the whole payload or the body are properly formatted.\n    function _body(MemView memView) private pure returns (MemView) {\n        return memView.sliceFrom({index_: OFFSET_BODY});\n    }\n}\n\n// contracts/base/AgentSecured.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for messaging contracts that are secured by the agent manager.\n * `AgentSecured` relies on `AgentManager` to provide the following functionality:\n * - Keep track of agents and their statuses.\n * - Pass agent-signed statements that were verified by the agent manager.\n * - These statements are considered valid indefinitely, unless the agent is disputed.\n * - Disputes are opened and resolved by the agent manager.\n * \u003e `AgentSecured` implementation should never use statements signed by agents that are disputed.\n */\nabstract contract AgentSecured is MessagingBase, IAgentSecured {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    address public immutable agentManager;\n\n    /// @inheritdoc IAgentSecured\n    address public immutable inbox;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    // (agent index =\u003e their dispute status: flag, openedAt, resolvedAt)\n    mapping(uint32 =\u003e DisputeStatus) internal _disputes;\n\n    /// @dev gap for upgrade safety\n    uint256[49] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    modifier onlyAgentManager() {\n        if (msg.sender != agentManager) revert CallerNotAgentManager();\n        _;\n    }\n\n    modifier onlyInbox() {\n        if (msg.sender != inbox) revert CallerNotInbox();\n        _;\n    }\n\n    constructor(string memory version_, uint32 synapseDomain_, address agentManager_, address inbox_)\n        MessagingBase(version_, synapseDomain_)\n    {\n        agentManager = agentManager_;\n        inbox = inbox_;\n    }\n\n    // ════════════════════════════════════════════ ONLY AGENT MANAGER ═════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external onlyAgentManager {\n        uint40 openedAt = ChainContext.blockTimestamp();\n        DisputeStatus memory status = DisputeStatus({flag: DisputeFlag.Pending, openedAt: openedAt, resolvedAt: 0});\n        _disputes[guardIndex] = status;\n        _disputes[notaryIndex] = status;\n    }\n\n    /// @inheritdoc IAgentSecured\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external onlyAgentManager {\n        // Update the dispute status of the slashed agent first.\n        uint40 resolvedAt = ChainContext.blockTimestamp();\n        _disputes[slashedIndex].flag = DisputeFlag.Slashed;\n        _disputes[slashedIndex].resolvedAt = resolvedAt;\n        // Mark the rival agent as not disputed, if there was an ongoing dispute.\n        if (rivalIndex != 0) {\n            _disputes[rivalIndex].flag = DisputeFlag.None;\n            _disputes[rivalIndex].resolvedAt = resolvedAt;\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function agentStatus(address agent) external view returns (AgentStatus memory) {\n        return _agentStatus(agent);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status) {\n        return _getAgent(index);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory) {\n        return _disputes[agentIndex];\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns status of the given agent: (flag, domain, index).\n    function _agentStatus(address agent) internal view returns (AgentStatus memory) {\n        return IAgentManager(agentManager).agentStatus(agent);\n    }\n\n    /// @dev Returns agent and their status for a given agent index. Returns zero values for non existing indexes.\n    function _getAgent(uint256 index) internal view returns (address agent, AgentStatus memory status) {\n        return IAgentManager(agentManager).getAgent(index);\n    }\n\n    /// @dev Checks if a Dispute exists for the given Notary. This function returns true, if\n    /// Notary is in ongoing Dispute, or if Dispute was resolved not in Notary's favor.\n    /// In both cases we can't trust Notary's data.\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeExists(uint32 notaryIndex) internal view returns (bool) {\n        return _disputes[notaryIndex].flag != DisputeFlag.None;\n    }\n\n    /// @dev Checks if a Notary recently won a Dispute and is still in the \"post-dispute\" timeout period.\n    /// In this period we still can't trust Notary's data, though we can optimistically assume that\n    /// that the data will be correct after the timeout (assuming no new Disputes are opened).\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeTimeout(uint32 notaryIndex) internal view returns (bool) {\n        DisputeStatus memory status = _disputes[notaryIndex];\n        // Exit early if Notary is in ongoing Dispute / slashed.\n        if (status.flag != DisputeFlag.None) return false;\n        // Check if Notary has been in any Dispute at all.\n        if (status.openedAt == 0) return false;\n        // Otherwise check if the Dispute timeout is still active.\n        return block.timestamp \u003c status.resolvedAt + DISPUTE_TIMEOUT_NOTARY;\n    }\n}\n\n// contracts/hubs/StateHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StateHub` is a parent contract for `Origin`. It is responsible for the following:\n/// - Keeping track of the historical Origin Merkle Tree containing all the message hashes.\n/// - Keeping track of the historical Origin States, as well as verifying their validity.\nabstract contract StateHub is AgentSecured, StateHubEvents, IStateHub {\n    using SafeCast for uint256;\n    using StateLib for bytes;\n\n    struct OriginState {\n        uint40 blockNumber;\n        uint40 timestamp;\n        GasData gasData;\n    }\n    // Bits left for tight packing: 80\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Historical Merkle Tree\n    /// Note: Takes two storage slots\n    HistoricalTree private _tree;\n\n    /// @dev All historical contract States\n    OriginState[] private _originStates;\n\n    /// @dev gap for upgrade safety\n    uint256[47] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IStateHub\n    function isValidState(bytes memory statePayload) external view returns (bool isValid) {\n        // This will revert if payload is not a formatted state\n        State state = statePayload.castToState();\n        return _isValidState(state);\n    }\n\n    /// @inheritdoc IStateHub\n    function statesAmount() external view returns (uint256) {\n        return _originStates.length;\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestLatestState() external view returns (bytes memory stateData) {\n        // This never underflows, assuming the contract was initialized\n        return suggestState(_nextNonce() - 1);\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestState(uint32 nonce) public view returns (bytes memory stateData) {\n        // This will revert if nonce is out of range\n        bytes32 root = _tree.root(nonce);\n        return _formatOriginState(_originStates[nonce], root, localDomain, nonce);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Initializes the saved states list by inserting a state for an empty Merkle Tree.\n    function _initializeStates() internal {\n        // This should only be called once, when the contract is initialized\n        // This will revert if _tree.roots is non-empty\n        bytes32 savedRoot = _tree.initializeRoots();\n        // Save root for empty merkle _tree with block number and timestamp of initialization\n        _saveState(savedRoot, _toOriginState());\n    }\n\n    /// @dev Inserts leaf into the Merkle Tree and saves the updated origin State.\n    function _insertAndSave(bytes32 leaf) internal {\n        bytes32 newRoot = _tree.insert(leaf);\n        _saveState(newRoot, _toOriginState());\n    }\n\n    /// @dev Saves an updated state of the Origin contract\n    function _saveState(bytes32 root, OriginState memory state) internal {\n        uint32 nonce = _nextNonce();\n        _originStates.push(state);\n        // Emit event with raw state data\n        emit StateSaved(_formatOriginState(state, root, localDomain, nonce));\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns nonce of the next sent message: the amount of saved States so far.\n    /// This always equals to \"total amount of sent messages\" plus 1.\n    function _nextNonce() internal view returns (uint32) {\n        // TODO: consider using more than 32 bits for origin nonces\n        return _originStates.length.toUint32();\n    }\n\n    /// @dev Checks if a state is valid, i.e. if it matches the historical one.\n    /// Reverts, if state refers to another Origin contract.\n    function _isValidState(State state) internal view returns (bool) {\n        // Check if state refers to this contract\n        if (state.origin() != localDomain) revert IncorrectOriginDomain();\n        // Check if nonce exists\n        uint32 nonce = state.nonce();\n        if (nonce \u003e= _originStates.length) return false;\n        // Check if state root matches the historical one\n        if (state.root() != _tree.root(nonce)) return false;\n        // Check if state metadata matches the historical one\n        return _areEqual(state, _originStates[nonce]);\n    }\n\n    // ═════════════════════════════════════════════ STRUCT FORMATTING ═════════════════════════════════════════════════\n\n    /// @dev Returns a formatted payload for a stored OriginState.\n    function _formatOriginState(OriginState memory originState, bytes32 root, uint32 origin, uint32 nonce)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return StateLib.formatState({\n            root_: root,\n            origin_: origin,\n            nonce_: nonce,\n            blockNumber_: originState.blockNumber,\n            timestamp_: originState.timestamp,\n            gasData_: originState.gasData\n        });\n    }\n\n    /// @dev Child contract should implement the logic for getting the current gas data from the gas oracle\n    /// to be saved as part of the Origin State.\n    // solhint-disable-next-line ordering\n    function _fetchGasData() internal view virtual returns (GasData);\n\n    /// @dev Returns a OriginState struct to save in the contract.\n    function _toOriginState() internal view returns (OriginState memory originState) {\n        originState.blockNumber = ChainContext.blockNumber();\n        originState.timestamp = ChainContext.blockTimestamp();\n        originState.gasData = _fetchGasData();\n    }\n\n    /// @dev Checks that a state and its Origin representation are equal.\n    function _areEqual(State state, OriginState memory originState) internal pure returns (bool) {\n        return state.blockNumber() == originState.blockNumber \u0026\u0026 state.timestamp() == originState.timestamp;\n    }\n}\n\n// contracts/Origin.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Origin` contract is used for sending messages to remote chains. It is done\n/// by inserting the message hashes into the Origin Merkle, which makes it possible to\n/// prove that message was sent using the Merkle proof against the Origin Merkle Root. This essentially\n/// compresses the list of messages into a single 32-byte value that needs to be stored on the destination chain.\n/// `Origin` is responsible for the following:\n/// - Formatting the sent message payloads, and inserting their hashes into the Origin Merkle Tree.\n/// - Keeping track of its own historical states (see parent contract `StateHub`).\n/// - Enforcing minimum tip values for sent base messages based on the provided execution requests.\n/// - Distributing the collected tips upon request from a local `AgentManager` contract.\ncontract Origin is StateHub, OriginEvents, InterfaceOrigin {\n    using MemViewLib for bytes;\n    using MessageLib for bytes;\n    using TipsLib for bytes;\n    using TypeCasts for address;\n\n    address public immutable gasOracle;\n\n    modifier onlyRemoteDestination(uint32 destination) {\n        if (destination == localDomain) revert IncorrectDestinationDomain();\n        _;\n    }\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_, address gasOracle_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {\n        gasOracle = gasOracle_;\n    }\n\n    /// @notice Initializes Origin contract:\n    /// - msg.sender is set as contract owner\n    /// - State of \"empty merkle tree\" is saved\n    function initialize() external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize \"states\": state of an \"empty merkle tree\" is saved\n        _initializeStates();\n    }\n\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable onlyRemoteDestination(destination) returns (uint32 messageNonce, bytes32 messageHash) {\n        // Check that content is not too large\n        if (content.length \u003e MAX_CONTENT_BYTES) revert ContentLengthTooBig();\n        // This will revert if msg.value is lower than value of minimum tips\n        Tips tips = _getMinimumTips(destination, paddedRequest, content.length).matchValue(msg.value);\n        Request request = RequestLib.wrapPadded(paddedRequest);\n        // Format the BaseMessage body\n        bytes memory body = BaseMessageLib.formatBaseMessage({\n            sender_: msg.sender.addressToBytes32(),\n            recipient_: recipient,\n            tips_: tips,\n            request_: request,\n            content_: content\n        });\n        // Send the message\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Base, body);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        onlyAgentManager\n        onlyRemoteDestination(destination)\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // AgentManager (checked via modifier) is responsible for constructing the calldata payload correctly.\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Manager, payload);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function withdrawTips(address recipient, uint256 amount) external onlyAgentManager {\n        if (address(this).balance \u003c amount) revert InsufficientEthBalance();\n        (bool success,) = recipient.call{value: amount}(\"\");\n        if (!success) revert EthTransferFailed();\n        emit TipWithdrawalCompleted(recipient, amount);\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue)\n    {\n        return _getMinimumTips(destination, paddedRequest, contentLength).value();\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Sends the given message to the specified destination. Message hash is inserted\n    /// into the Origin Merkle Tree, which will enable message execution on destination chain.\n    function _sendMessage(uint32 destination, uint32 optimisticPeriod, MessageFlag flag, bytes memory body)\n        internal\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // Format the message header\n        messageNonce = _nextNonce();\n        Header header = flag.encodeHeader({\n            origin_: localDomain,\n            nonce_: messageNonce,\n            destination_: destination,\n            optimisticPeriod_: optimisticPeriod\n        });\n        // Format the full message payload\n        bytes memory msgPayload = MessageLib.formatMessage(header, body);\n        // Insert new leaf into the Origin Merkle Tree and save the updated state\n        messageHash = msgPayload.castToMessage().leaf();\n        _insertAndSave(messageHash);\n        // Emit event with message information\n        emit Sent(messageHash, messageNonce, destination, msgPayload);\n        // Update the gas oracle data. We do this after the provided tips are checked so that\n        // the provided message is sent in the event that the gas oracle data is updated to a higher value.\n        InterfaceGasOracle(gasOracle).updateGasData(destination);\n        // TODO: consider doing this before the message is sent, while adjusting GasOracle.getMinimumTips() to\n        // use the pending gas oracle data.\n    }\n\n    /// @dev Returns the minimum tips for sending a message to the given destination with the given request and content.\n    function _getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        internal\n        view\n        returns (Tips)\n    {\n        return\n            TipsLib.wrapPadded(InterfaceGasOracle(gasOracle).getMinimumTips(destination, paddedRequest, contentLength));\n    }\n\n    /// @dev Gets the current gas data from the gas oracle to be saved as part of the Origin State.\n    function _fetchGasData() internal view override returns (GasData) {\n        return GasDataLib.wrapGasData(InterfaceGasOracle(gasOracle).getGasData());\n    }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"76441:976:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;76441:976:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"76441:976:0:-:0;;;;;;;;","abiDefinition":[],"userDoc":{"kind":"user","methods":{},"notice":"Library for accessing chain context variables as tightly packed integers. Messaging contracts should rely on this library for accessing chain context variables instead of doing the casting themselves.","version":1},"developerDoc":{"kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"Library for accessing chain context variables as tightly packed integers. Messaging contracts should rely on this library for accessing chain context variables instead of doing the casting themselves.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Origin.sol\":\"ChainContext\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Origin.sol\":{\"keccak256\":\"0x96775924f147f3d1f8df8cdf56731fe52a15af8d8e12e608efb8158c112b18cd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e642a27f5fab3c62b4c02e9754e9e42b1cf2e5381dbea9d3d106d23b7772ebe6\",\"dweb:/ipfs/QmUwn7ZyBvPkjnMuK8ZMSexBUdNQnVtxwyoAyT4DXLQjra\"]}},\"version\":1}"},"hashes":{}},"solidity/Origin.sol:ContextUpgradeable":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/OriginEvents.sol\n\n/// @notice A collection of events emitted by the Origin contract\nabstract contract OriginEvents {\n    /**\n     * @notice Emitted when a new message is sent.\n     * @param messageHash   Hash of message; the leaf inserted to the Merkle tree for the message\n     * @param nonce         Nonce of sent message (starts from 1)\n     * @param destination   Destination domain\n     * @param message       Raw bytes of message\n     */\n    event Sent(bytes32 indexed messageHash, uint32 indexed nonce, uint32 indexed destination, bytes message);\n\n    /**\n     * @notice Emitted when a tip withdrawal is completed.\n     * @param actor     Actor address\n     * @param tip       Tip value, denominated in local domain's wei\n     */\n    event TipWithdrawalCompleted(address actor, uint256 tip);\n}\n\n// contracts/events/StateHubEvents.sol\n\n/// @notice A collection of events emitted by the StateHub contract\nabstract contract StateHubEvents {\n    /**\n     * @notice Emitted when a new Origin State is saved after a message was sent.\n     * @param state     Raw payload with state data\n     */\n    event StateSaved(bytes state);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n    /**\n     * @notice Check that a given state is valid: matches the historical state of Origin contract.\n     * Note: any Agent including an invalid state in their snapshot will be slashed\n     * upon providing the snapshot and agent signature for it to Origin contract.\n     * @dev Will revert if any of these is true:\n     *  - State payload is not properly formatted.\n     * @param statePayload      Raw payload with state data\n     * @return isValid          Whether the provided state is valid\n     */\n    function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns the amount of saved states so far.\n     * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n     */\n    function statesAmount() external view returns (uint256);\n\n    /**\n     * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @return statePayload     Raw payload with the latest state data\n     */\n    function suggestLatestState() external view returns (bytes memory statePayload);\n\n    /**\n     * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @param nonce             Historical nonce to form a state\n     * @return statePayload     Raw payload with historical state data\n     */\n    function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/InterfaceGasOracle.sol\n\ninterface InterfaceGasOracle {\n    /**\n     * @notice Fetches the latest gas data for the chain from `Destination` contract,\n     * and uses it to update the oracle values for the requested chain.\n     * @param domain    Domain to update the gas data for\n     */\n    function updateGasData(uint32 domain) external;\n\n    /**\n     * @notice Returns the gas data for the local chain.\n     */\n    function getGasData() external view returns (uint256 paddedGasData);\n\n    /**\n     * @notice Returns the gas data for the given domain, in the decoded format.\n     * @param domain        Domain of chain to get gas data for\n     * @return gasPrice     Gas price for the chain (in Wei per gas unit)\n     * @return dataPrice    Calldata price (in Wei per byte of content)\n     * @return execBuffer   Tx fee safety buffer for message execution (in Wei)\n     * @return amortAttCost Amortized cost for attestation submission (in Wei)\n     * @return etherPrice   Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n     * @return markup       Markup for the message execution (in BWAD)\n     */\n    function getDecodedGasData(uint32 domain)\n        external\n        view\n        returns (\n            uint256 gasPrice,\n            uint256 dataPrice,\n            uint256 execBuffer,\n            uint256 amortAttCost,\n            uint256 etherPrice,\n            uint256 markup\n        );\n\n    /**\n     * @notice Returns the minimum tips for sending a message to a given destination.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return paddedTips       Padded encoded minimum tips information\n     */\n    function getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 paddedTips);\n}\n\n// contracts/interfaces/InterfaceOrigin.sol\n\ninterface InterfaceOrigin {\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /**\n     * @notice Send a message to the recipient located on destination domain.\n     * @dev Recipient has to conform to IMessageRecipient interface, otherwise message won't be delivered.\n     * Will revert if any of these is true:\n     * - `destination` is equal to contract's local domain\n     * - `content` length is greater than `MAX_CONTENT_BYTES`\n     * - `msg.value` is lower than value of minimum tips for the given message\n     * @param destination           Domain of destination chain\n     * @param recipient             Address of recipient on destination chain as bytes32\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param paddedRequest         Padded encoded message execution request on destination chain\n     * @param content               Raw bytes content of message\n     * @return messageNonce         Nonce of the sent message\n     * @return messageHash          Hash of the sent message\n     */\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable returns (uint32 messageNonce, bytes32 messageHash);\n\n    /**\n     * @notice Send a manager message to the destination domain.\n     * @dev This could only be called by AgentManager, which takes care of encoding the calldata payload.\n     * Note: (msgOrigin, proofMaturity) security args will be added to payload on the destination chain\n     * so that the AgentManager could verify where the Manager Message came from and how mature is the proof.\n     * Note: function is not payable, as no tips are required for sending a manager message.\n     * Will revert if `destination` is equal to contract's local domain.\n     * @param destination           Domain of destination chain\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param payload               Payload for calling AgentManager on destination chain (with extra security args)\n     */\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        returns (uint32 messageNonce, bytes32 messageHash);\n\n    // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Withdraws locked base message tips to the recipient.\n     * @dev Could only be called by a local AgentManager.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function withdrawTips(address recipient, uint256 amount) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the minimum tips value for sending a message to a given destination.\n     * @dev Using at least `tipsValue` as `msg.value` for `sendBaseMessage()`\n     * will guarantee that the message will be accepted.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return tipsValue        Minimum tips value for a message to be accepted\n     */\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue);\n}\n\n// contracts/libs/Constants.sol\n\n// Here we define common constants to enable their easier reusing later.\n\n// ══════════════════════════════════ MERKLE ═══════════════════════════════════\n/// @dev Height of the Agent Merkle Tree\nuint256 constant AGENT_TREE_HEIGHT = 32;\n/// @dev Height of the Origin Merkle Tree\nuint256 constant ORIGIN_TREE_HEIGHT = 32;\n/// @dev Height of the Snapshot Merkle Tree. Allows up to 64 leafs, e.g. up to 32 states\nuint256 constant SNAPSHOT_TREE_HEIGHT = 6;\n// ══════════════════════════════════ STRUCTS ══════════════════════════════════\n/// @dev See Attestation.sol: (bytes32,bytes32,uint32,uint40,uint40): 32+32+4+5+5\nuint256 constant ATTESTATION_LENGTH = 78;\n/// @dev See GasData.sol: (uint16,uint16,uint16,uint16,uint16,uint16): 2+2+2+2+2+2\nuint256 constant GAS_DATA_LENGTH = 12;\n/// @dev See Receipt.sol: (uint32,uint32,bytes32,bytes32,uint8,address,address,address): 4+4+32+32+1+20+20+20\nuint256 constant RECEIPT_LENGTH = 133;\n/// @dev See State.sol: (bytes32,uint32,uint32,uint40,uint40,GasData): 32+4+4+5+5+len(GasData)\nuint256 constant STATE_LENGTH = 50 + GAS_DATA_LENGTH;\n/// @dev Maximum amount of states in a single snapshot. Each state produces two leafs in the tree\nuint256 constant SNAPSHOT_MAX_STATES = 1 \u003c\u003c (SNAPSHOT_TREE_HEIGHT - 1);\n// ══════════════════════════════════ MESSAGE ══════════════════════════════════\n/// @dev See Header.sol: (uint8,uint32,uint32,uint32,uint32): 1+4+4+4+4\nuint256 constant HEADER_LENGTH = 17;\n/// @dev See Request.sol: (uint96,uint64,uint32): 12+8+4\nuint256 constant REQUEST_LENGTH = 24;\n/// @dev See Tips.sol: (uint64,uint64,uint64,uint64): 8+8+8+8\nuint256 constant TIPS_LENGTH = 32;\n/// @dev The amount of discarded last bits when encoding tip values\nuint256 constant TIPS_GRANULARITY = 32;\n/// @dev Tip values could be only the multiples of TIPS_MULTIPLIER\nuint256 constant TIPS_MULTIPLIER = 1 \u003c\u003c TIPS_GRANULARITY;\n// ══════════════════════════════ STATEMENT SALTS ══════════════════════════════\n/// @dev Salts for signing various statements\nbytes32 constant ATTESTATION_VALID_SALT = keccak256(\"ATTESTATION_VALID_SALT\");\nbytes32 constant ATTESTATION_INVALID_SALT = keccak256(\"ATTESTATION_INVALID_SALT\");\nbytes32 constant RECEIPT_VALID_SALT = keccak256(\"RECEIPT_VALID_SALT\");\nbytes32 constant RECEIPT_INVALID_SALT = keccak256(\"RECEIPT_INVALID_SALT\");\nbytes32 constant SNAPSHOT_VALID_SALT = keccak256(\"SNAPSHOT_VALID_SALT\");\nbytes32 constant STATE_INVALID_SALT = keccak256(\"STATE_INVALID_SALT\");\n// ═════════════════════════════════ PROTOCOL ══════════════════════════════════\n/// @dev Optimistic period for new agent roots in LightManager\nuint32 constant AGENT_ROOT_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Timeout between the agent root could be proposed and resolved in LightManager\nuint32 constant AGENT_ROOT_PROPOSAL_TIMEOUT = 12 hours;\nuint32 constant BONDING_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Amount of time that the Notary will not be considered active after they won a dispute\nuint32 constant DISPUTE_TIMEOUT_NOTARY = 12 hours;\n/// @dev Amount of time without fresh data from Notaries before contract owner can resolve stuck disputes manually\nuint256 constant FRESH_DATA_TIMEOUT = 4 hours;\n/// @dev Maximum bytes per message = 2 KiB (somewhat arbitrarily set to begin)\nuint256 constant MAX_CONTENT_BYTES = 2 * 2 ** 10;\n/// @dev Maximum value for the summit tip that could be set in GasOracle\nuint256 constant MAX_SUMMIT_TIP = 0.01 ether;\n\n// contracts/libs/Errors.sol\n\n// ══════════════════════════════ INVALID CALLER ═══════════════════════════════\n\nerror CallerNotAgentManager();\nerror CallerNotDestination();\nerror CallerNotInbox();\nerror CallerNotSummit();\n\n// ══════════════════════════════ INCORRECT DATA ═══════════════════════════════\n\nerror IncorrectAttestation();\nerror IncorrectAgentDomain();\nerror IncorrectAgentIndex();\nerror IncorrectAgentProof();\nerror IncorrectAgentRoot();\nerror IncorrectDataHash();\nerror IncorrectDestinationDomain();\nerror IncorrectOriginDomain();\nerror IncorrectSnapshotProof();\nerror IncorrectSnapshotRoot();\nerror IncorrectState();\nerror IncorrectStatesAmount();\nerror IncorrectTipsProof();\nerror IncorrectVersionLength();\n\nerror IncorrectNonce();\nerror IncorrectSender();\nerror IncorrectRecipient();\n\nerror FlagOutOfRange();\nerror IndexOutOfRange();\nerror NonceOutOfRange();\n\nerror OutdatedNonce();\n\nerror UnformattedAttestation();\nerror UnformattedAttestationReport();\nerror UnformattedBaseMessage();\nerror UnformattedCallData();\nerror UnformattedCallDataPrefix();\nerror UnformattedMessage();\nerror UnformattedReceipt();\nerror UnformattedReceiptReport();\nerror UnformattedSignature();\nerror UnformattedSnapshot();\nerror UnformattedState();\nerror UnformattedStateReport();\n\n// ═══════════════════════════════ MERKLE TREES ════════════════════════════════\n\nerror LeafNotProven();\nerror MerkleTreeFull();\nerror NotEnoughLeafs();\nerror TreeHeightTooLow();\n\n// ═════════════════════════════ OPTIMISTIC PERIOD ═════════════════════════════\n\nerror BaseClientOptimisticPeriod();\nerror MessageOptimisticPeriod();\nerror SlashAgentOptimisticPeriod();\nerror WithdrawTipsOptimisticPeriod();\nerror ZeroProofMaturity();\n\n// ═══════════════════════════════ AGENT MANAGER ═══════════════════════════════\n\nerror AgentNotGuard();\nerror AgentNotNotary();\n\nerror AgentCantBeAdded();\nerror AgentNotActive();\nerror AgentNotActiveNorUnstaking();\nerror AgentNotFraudulent();\nerror AgentNotUnstaking();\nerror AgentUnknown();\n\nerror AgentRootNotProposed();\nerror AgentRootTimeoutNotOver();\n\nerror NotStuck();\n\nerror DisputeAlreadyResolved();\nerror DisputeNotOpened();\nerror DisputeTimeoutNotOver();\nerror GuardInDispute();\nerror NotaryInDispute();\n\nerror MustBeSynapseDomain();\nerror SynapseDomainForbidden();\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\nerror AlreadyExecuted();\nerror AlreadyFailed();\nerror DuplicatedSnapshotRoot();\nerror IncorrectMagicValue();\nerror GasLimitTooLow();\nerror GasSuppliedTooLow();\n\n// ══════════════════════════════════ ORIGIN ═══════════════════════════════════\n\nerror ContentLengthTooBig();\nerror EthTransferFailed();\nerror InsufficientEthBalance();\n\n// ════════════════════════════════ GAS ORACLE ═════════════════════════════════\n\nerror LocalGasDataNotSet();\nerror RemoteGasDataNotSet();\n\n// ═══════════════════════════════════ TIPS ════════════════════════════════════\n\nerror SummitTipTooHigh();\nerror TipsClaimMoreThanEarned();\nerror TipsClaimZero();\nerror TipsOverflow();\nerror TipsValueTooLow();\n\n// ════════════════════════════════ MEMORY VIEW ════════════════════════════════\n\nerror IndexedTooMuch();\nerror ViewOverrun();\nerror OccupiedMemory();\nerror UnallocatedMemory();\nerror PrecompileOutOfGas();\n\n// ═════════════════════════════════ MULTICALL ═════════════════════════════════\n\nerror MulticallFailed();\n\n// contracts/libs/TypeCasts.sol\n\nlibrary TypeCasts {\n    // alignment preserving cast\n    function addressToBytes32(address addr) internal pure returns (bytes32) {\n        return bytes32(uint256(uint160(addr)));\n    }\n\n    // alignment preserving cast\n    function bytes32ToAddress(bytes32 buf) internal pure returns (address) {\n        return address(uint160(uint256(buf)));\n    }\n}\n\n// contracts/libs/stack/Number.sol\n\n/// Number is a compact representation of uint256, that is fit into 16 bits\n/// with the maximum relative error under 0.4%.\ntype Number is uint16;\n\nusing NumberLib for Number global;\n\n/// # Number\n/// Library for compact representation of uint256 numbers.\n/// - Number is stored using mantissa and exponent, each occupying 8 bits.\n/// - Numbers under 2**8 are stored as `mantissa` with `exponent = 0xFF`.\n/// - Numbers at least 2**8 are approximated as `(256 + mantissa) \u003c\u003c exponent`\n/// \u003e - `0 \u003c= mantissa \u003c 256`\n/// \u003e - `0 \u003c= exponent \u003c= 247` (`256 * 2**248` doesn't fit into uint256)\n/// # Number stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type  | Bytes |\n/// | ---------- | -------- | ----- | ----- |\n/// | (002..001] | mantissa | uint8 | 1     |\n/// | (001..000] | exponent | uint8 | 1     |\n\nlibrary NumberLib {\n    /// @dev Amount of bits to shift to mantissa field\n    uint16 private constant SHIFT_MANTISSA = 8;\n\n    /// @notice For bwad math (binary wad) we use 2**64 as \"wad\" unit.\n    /// @dev We are using not using 10**18 as wad, because it is not stored precisely in NumberLib.\n    uint256 internal constant BWAD_SHIFT = 64;\n    uint256 internal constant BWAD = 1 \u003c\u003c BWAD_SHIFT;\n    /// @notice ~0.1% in bwad units.\n    uint256 internal constant PER_MILLE_SHIFT = BWAD_SHIFT - 10;\n    uint256 internal constant PER_MILLE = 1 \u003c\u003c PER_MILLE_SHIFT;\n\n    /// @notice Compresses uint256 number into 16 bits.\n    function compress(uint256 value) internal pure returns (Number) {\n        // Find `msb` such as `2**msb \u003c= value \u003c 2**(msb + 1)`\n        uint256 msb = mostSignificantBit(value);\n        // We want to preserve 9 bits of precision.\n        // The highest bit is always 1, so we can skip it.\n        // The remaining 8 highest bits are stored as mantissa.\n        if (msb \u003c 8) {\n            // Value is less than 2**8, so we can use value as mantissa with \"-1\" exponent.\n            return _encode(uint8(value), 0xFF);\n        } else {\n            // We use `msb - 8` as exponent otherwise. Note that `exponent \u003e= 0`.\n            unchecked {\n                uint256 exponent = msb - 8;\n                // Shifting right by `msb-8` bits will shift the \"remaining 8 highest bits\" into the 8 lowest bits.\n                // uint8() will truncate the highest bit.\n                return _encode(uint8(value \u003e\u003e exponent), uint8(exponent));\n            }\n        }\n    }\n\n    /// @notice Decompresses 16 bits number into uint256.\n    /// @dev The outcome is an approximation of the original number: `(value - value / 256) \u003c number \u003c= value`.\n    function decompress(Number number) internal pure returns (uint256 value) {\n        // Isolate 8 highest bits as the mantissa.\n        uint256 mantissa = Number.unwrap(number) \u003e\u003e SHIFT_MANTISSA;\n        // This will truncate the highest bits, leaving only the exponent.\n        uint256 exponent = uint8(Number.unwrap(number));\n        if (exponent == 0xFF) {\n            return mantissa;\n        } else {\n            unchecked {\n                return (256 + mantissa) \u003c\u003c (exponent);\n            }\n        }\n    }\n\n    /// @dev Returns the most significant bit of `x`\n    /// https://solidity-by-example.org/bitwise/\n    function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\n        // To find `msb` we determine it bit by bit, starting from the highest one.\n        // `0 \u003c= msb \u003c= 255`, so we start from the highest bit, 1\u003c\u003c7 == 128.\n        // If `x` is at least 2**128, then the highest bit of `x` is at least 128.\n        // solhint-disable no-inline-assembly\n        assembly {\n            // `f` is set to 1\u003c\u003c7 if `x \u003e= 2**128` and to 0 otherwise.\n            let f := shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\n            // If `x \u003e= 2**128` then set `msb` highest bit to 1 and shift `x` right by 128.\n            // Otherwise, `msb` remains 0 and `x` remains unchanged.\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        // `x` is now at most 2**128 - 1. Continue the same way, the next highest bit is 1\u003c\u003c6 == 64.\n        assembly {\n            // `f` is set to 1\u003c\u003c6 if `x \u003e= 2**64` and to 0 otherwise.\n            let f := shl(6, gt(x, 0xFFFFFFFFFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c5 if `x \u003e= 2**32` and to 0 otherwise.\n            let f := shl(5, gt(x, 0xFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c4 if `x \u003e= 2**16` and to 0 otherwise.\n            let f := shl(4, gt(x, 0xFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c3 if `x \u003e= 2**8` and to 0 otherwise.\n            let f := shl(3, gt(x, 0xFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c2 if `x \u003e= 2**4` and to 0 otherwise.\n            let f := shl(2, gt(x, 0xF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c1 if `x \u003e= 2**2` and to 0 otherwise.\n            let f := shl(1, gt(x, 0x3))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1 if `x \u003e= 2**1` and to 0 otherwise.\n            let f := gt(x, 0x1)\n            msb := or(msb, f)\n        }\n    }\n\n    /// @dev Wraps (mantissa, exponent) pair into Number.\n    function _encode(uint8 mantissa, uint8 exponent) private pure returns (Number) {\n        // Casts below are upcasts, so they are safe.\n        return Number.wrap(uint16(mantissa) \u003c\u003c SHIFT_MANTISSA | uint16(exponent));\n    }\n}\n\n// contracts/libs/stack/Request.sol\n\n/// Request is encoded data with \"message execution request\".\ntype Request is uint192;\n\nusing RequestLib for Request global;\n\n/// Library for formatting _the request part_ of _the base messages_.\n/// - Request represents a message sender requirements for the message execution on the destination chain.\n/// - Request occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n/// \u003e gasDrop field is included for future compatibility and is ignored at the moment.\n///\n/// # Request stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type   | Bytes | Description                                          |\n/// | ---------- | -------- | ------ | ----- | ---------------------------------------------------- |\n/// | (024..012] | gasDrop  | uint96 | 12    | Minimum amount of gas token to drop to the recipient |\n/// | (012..004] | gasLimit | uint64 | 8     | Minimum amount of gas units to supply for execution  |\n/// | (004..000] | version  | uint32 | 4     | Base message version to pass to the recipient        |\n\nlibrary RequestLib {\n    /// @dev Amount of bits to shift to gasDrop field\n    uint192 private constant SHIFT_GAS_DROP = 12 * 8;\n    /// @dev Amount of bits to shift to gasLimit field\n    uint192 private constant SHIFT_GAS_LIMIT = 4 * 8;\n\n    /// @notice Returns an encoded request with the given fields\n    /// @param gasDrop_     Minimum amount of gas token to drop to the recipient (ignored at the moment)\n    /// @param gasLimit_    Minimum amount of gas units to supply for execution\n    /// @param version_     Base message version to pass to the recipient\n    function encodeRequest(uint96 gasDrop_, uint64 gasLimit_, uint32 version_) internal pure returns (Request) {\n        // Casts below are upcasts, so they are safe\n        return Request.wrap(uint192(gasDrop_) \u003c\u003c SHIFT_GAS_DROP | uint192(gasLimit_) \u003c\u003c SHIFT_GAS_LIMIT | version_);\n    }\n\n    /// @notice Wraps the padded encoded request into a Request-typed value.\n    /// @dev The \"padded\" request is simply an encoded request casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded requests\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedRequest) internal pure returns (Request) {\n        // Casting to uint192 will truncate the highest bits, which is the behavior we want\n        return Request.wrap(uint192(paddedRequest));\n    }\n\n    /// @notice Returns the requested of gas token to drop to the recipient.\n    function gasDrop(Request request) internal pure returns (uint96) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return uint96(Request.unwrap(request) \u003e\u003e SHIFT_GAS_DROP);\n    }\n\n    /// @notice Returns the requested minimum amount of gas units to supply for execution.\n    function gasLimit(Request request) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Request.unwrap(request) \u003e\u003e SHIFT_GAS_LIMIT);\n    }\n\n    /// @notice Returns the requested base message version to pass to the recipient.\n    function version(Request request) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Request.unwrap(request));\n    }\n}\n\n// node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        require(value \u003c= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        require(value \u003c= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        require(value \u003c= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value \u003c= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        require(value \u003c= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        require(value \u003c= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        require(value \u003c= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        require(value \u003c= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        require(value \u003c= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        require(value \u003c= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        require(value \u003c= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        require(value \u003c= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        require(value \u003c= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        require(value \u003c= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        require(value \u003c= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value \u003c= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        require(value \u003c= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        require(value \u003c= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        require(value \u003c= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value \u003c= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        require(value \u003c= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        require(value \u003c= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        require(value \u003c= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value \u003c= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        require(value \u003c= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        require(value \u003c= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        require(value \u003c= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value \u003c= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        require(value \u003c= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value \u003c= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value \u003c= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     *\n     * _Available since v3.0._\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value \u003e= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     *\n     * _Available since v3.0._\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value \u003c= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     *\n     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length \u003e 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance \u003e= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance \u003e= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length \u003e 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n\n// contracts/base/MultiCallable.sol\n\n/// @notice Collection of Multicall utilities. Fork of Multicall3:\n/// https://github.com/mds1/multicall/blob/master/src/Multicall3.sol\nabstract contract MultiCallable {\n    struct Call {\n        bool allowFailure;\n        bytes callData;\n    }\n\n    struct Result {\n        bool success;\n        bytes returnData;\n    }\n\n    /// @notice Aggregates a few calls to this contract into one multicall without modifying `msg.sender`.\n    function multicall(Call[] calldata calls) external returns (Result[] memory callResults) {\n        uint256 amount = calls.length;\n        callResults = new Result[](amount);\n        Call calldata call_;\n        for (uint256 i = 0; i \u003c amount;) {\n            call_ = calls[i];\n            Result memory result = callResults[i];\n            // We perform a delegate call to ourselves here. Delegate call does not modify `msg.sender`, so\n            // this will have the same effect as if `msg.sender` performed all the calls themselves one by one.\n            // solhint-disable-next-line avoid-low-level-calls\n            (result.success, result.returnData) = address(this).delegatecall(call_.callData);\n            // solhint-disable-next-line no-inline-assembly\n            assembly {\n                // Revert if the call fails and failure is not allowed\n                // `allowFailure := calldataload(call_)` and `success := mload(result)`\n                if iszero(or(calldataload(call_), mload(result))) {\n                    // Revert with `0x4d6a2328` (function selector for `MulticallFailed()`)\n                    mstore(0x00, 0x4d6a232800000000000000000000000000000000000000000000000000000000)\n                    revert(0x00, 0x04)\n                }\n            }\n            unchecked {\n                ++i;\n            }\n        }\n    }\n}\n\n// contracts/base/Version.sol\n\n/**\n * @title Versioned\n * @notice Version getter for contracts. Doesn't use any storage slots, meaning\n * it will never cause any troubles with the upgradeable contracts. For instance, this contract\n * can be added or removed from the inheritance chain without shifting the storage layout.\n */\nabstract contract Versioned {\n    /**\n     * @notice Struct that is mimicking the storage layout of a string with 32 bytes or less.\n     * Length is limited by 32, so the whole string payload takes two memory words:\n     * @param length    String length\n     * @param data      String characters\n     */\n    struct _ShortString {\n        uint256 length;\n        bytes32 data;\n    }\n\n    /// @dev Length of the \"version string\"\n    uint256 private immutable _length;\n    /// @dev Bytes representation of the \"version string\".\n    /// Strings with length over 32 are not supported!\n    bytes32 private immutable _data;\n\n    constructor(string memory version_) {\n        _length = bytes(version_).length;\n        if (_length \u003e 32) revert IncorrectVersionLength();\n        // bytes32 is left-aligned =\u003e this will store the byte representation of the string\n        // with the trailing zeroes to complete the 32-byte word\n        _data = bytes32(bytes(version_));\n    }\n\n    function version() external view returns (string memory versionString) {\n        // Load the immutable values to form the version string\n        _ShortString memory str = _ShortString(_length, _data);\n        // The only way to do this cast is doing some dirty assembly\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            versionString := str\n        }\n    }\n}\n\n// contracts/libs/ChainContext.sol\n\n/// @notice Library for accessing chain context variables as tightly packed integers.\n/// Messaging contracts should rely on this library for accessing chain context variables\n/// instead of doing the casting themselves.\nlibrary ChainContext {\n    using SafeCast for uint256;\n\n    /// @notice Returns the current block number as uint40.\n    /// @dev Reverts if block number is greater than 40 bits, which is not supposed to happen\n    /// until the block.timestamp overflows (assuming block time is at least 1 second).\n    function blockNumber() internal view returns (uint40) {\n        return block.number.toUint40();\n    }\n\n    /// @notice Returns the current block timestamp as uint40.\n    /// @dev Reverts if block timestamp is greater than 40 bits, which is\n    /// supposed to happen approximately in year 36835.\n    function blockTimestamp() internal view returns (uint40) {\n        return block.timestamp.toUint40();\n    }\n\n    /// @notice Returns the chain id as uint32.\n    /// @dev Reverts if chain id is greater than 32 bits, which is not\n    /// supposed to happen in production.\n    function chainId() internal view returns (uint32) {\n        return block.chainid.toUint32();\n    }\n}\n\n// contracts/libs/Structures.sol\n\n// Here we define common enums and structures to enable their easier reusing later.\n\n// ═══════════════════════════════ AGENT STATUS ════════════════════════════════\n\n/// @dev Potential statuses for the off-chain bonded agent:\n/// - Unknown: never provided a bond =\u003e signature not valid\n/// - Active: has a bond in BondingManager =\u003e signature valid\n/// - Unstaking: has a bond in BondingManager, initiated the unstaking =\u003e signature not valid\n/// - Resting: used to have a bond in BondingManager, successfully unstaked =\u003e signature not valid\n/// - Fraudulent: proven to commit fraud, value in Merkle Tree not updated =\u003e signature not valid\n/// - Slashed: proven to commit fraud, value in Merkle Tree was updated =\u003e signature not valid\n/// Unstaked agent could later be added back to THE SAME domain by staking a bond again.\n/// Honest agent: Unknown -\u003e Active -\u003e unstaking -\u003e Resting -\u003e Active ...\n/// Malicious agent: Unknown -\u003e Active -\u003e Fraudulent -\u003e Slashed\n/// Malicious agent: Unknown -\u003e Active -\u003e Unstaking -\u003e Fraudulent -\u003e Slashed\nenum AgentFlag {\n    Unknown,\n    Active,\n    Unstaking,\n    Resting,\n    Fraudulent,\n    Slashed\n}\n\n/// @notice Struct for storing an agent in the BondingManager contract.\nstruct AgentStatus {\n    AgentFlag flag;\n    uint32 domain;\n    uint32 index;\n}\n// 184 bits available for tight packing\n\nusing StructureUtils for AgentStatus global;\n\n/// @notice Potential statuses of an agent in terms of being in dispute\n/// - None: agent is not in dispute\n/// - Pending: agent is in unresolved dispute\n/// - Slashed: agent was in dispute that lead to agent being slashed\n/// Note: agent who won the dispute has their status reset to None\nenum DisputeFlag {\n    None,\n    Pending,\n    Slashed\n}\n\n/// @notice Struct for storing dispute status of an agent.\n/// @param flag         Dispute flag: None/Pending/Slashed.\n/// @param openedAt     Timestamp when the latest agent dispute was opened (zero if not opened).\n/// @param resolvedAt   Timestamp when the latest agent dispute was resolved (zero if not resolved).\nstruct DisputeStatus {\n    DisputeFlag flag;\n    uint40 openedAt;\n    uint40 resolvedAt;\n}\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\n/// @notice Struct representing the status of Destination contract.\n/// @param snapRootTime     Timestamp when latest snapshot root was accepted\n/// @param agentRootTime    Timestamp when latest agent root was accepted\n/// @param notaryIndex      Index of Notary who signed the latest agent root\nstruct DestinationStatus {\n    uint40 snapRootTime;\n    uint40 agentRootTime;\n    uint32 notaryIndex;\n}\n\n// ═══════════════════════════════ EXECUTION HUB ═══════════════════════════════\n\n/// @notice Potential statuses of the message in Execution Hub.\n/// - None: there hasn't been a valid attempt to execute the message yet\n/// - Failed: there was a valid attempt to execute the message, but recipient reverted\n/// - Success: there was a valid attempt to execute the message, and recipient did not revert\n/// Note: message can be executed until its status is Success\nenum MessageStatus {\n    None,\n    Failed,\n    Success\n}\n\nlibrary StructureUtils {\n    /// @notice Checks that Agent is Active\n    function verifyActive(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active) {\n            revert AgentNotActive();\n        }\n    }\n\n    /// @notice Checks that Agent is Unstaking\n    function verifyUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Unstaking) {\n            revert AgentNotUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Active or Unstaking\n    function verifyActiveUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active \u0026\u0026 status.flag != AgentFlag.Unstaking) {\n            revert AgentNotActiveNorUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Fraudulent\n    function verifyFraudulent(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Fraudulent) {\n            revert AgentNotFraudulent();\n        }\n    }\n\n    /// @notice Checks that Agent is not Unknown\n    function verifyKnown(AgentStatus memory status) internal pure {\n        if (status.flag == AgentFlag.Unknown) {\n            revert AgentUnknown();\n        }\n    }\n}\n\n// contracts/libs/memory/MemView.sol\n\n/// @dev MemView is an untyped view over a portion of memory to be used instead of `bytes memory`\ntype MemView is uint256;\n\n/// @dev Attach library functions to MemView\nusing MemViewLib for MemView global;\n\n/// @notice Library for operations with the memory views.\n/// Forked from https://github.com/summa-tx/memview-sol with several breaking changes:\n/// - The codebase is ported to Solidity 0.8\n/// - Custom errors are added\n/// - The runtime type checking is replaced with compile-time check provided by User-Defined Value Types\n///   https://docs.soliditylang.org/en/latest/types.html#user-defined-value-types\n/// - uint256 is used as the underlying type for the \"memory view\" instead of bytes29.\n///   It is wrapped into MemView custom type in order not to be confused with actual integers.\n/// - Therefore the \"type\" field is discarded, allowing to allocate 16 bytes for both view location and length\n/// - The documentation is expanded\n/// - Library functions unused by the rest of the codebase are removed\n//  - Very pretty code separators are added :)\nlibrary MemViewLib {\n    /// @notice Stack layout for uint256 (from highest bits to lowest)\n    /// (32 .. 16]      loc     16 bytes    Memory address of underlying bytes\n    /// (16 .. 00]      len     16 bytes    Length of underlying bytes\n\n    // ═══════════════════════════════════════════ BUILDING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Instantiate a new untyped memory view. This should generally not be called directly.\n     * Prefer `ref` wherever possible.\n     * @param loc_          The memory address\n     * @param len_          The length\n     * @return The new view with the specified location and length\n     */\n    function build(uint256 loc_, uint256 len_) internal pure returns (MemView) {\n        uint256 end_ = loc_ + len_;\n        // Make sure that a view is not constructed that points to unallocated memory\n        // as this could be indicative of a buffer overflow attack\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            if gt(end_, mload(0x40)) { end_ := 0 }\n        }\n        if (end_ == 0) {\n            revert UnallocatedMemory();\n        }\n        return _unsafeBuildUnchecked(loc_, len_);\n    }\n\n    /**\n     * @notice Instantiate a memory view from a byte array.\n     * @dev Note that due to Solidity memory representation, it is not possible to\n     * implement a deref, as the `bytes` type stores its len in memory.\n     * @param arr           The byte array\n     * @return The memory view over the provided byte array\n     */\n    function ref(bytes memory arr) internal pure returns (MemView) {\n        uint256 len_ = arr.length;\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 loc_;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // We add 0x20, so that the view starts exactly where the array data starts\n            loc_ := add(arr, 0x20)\n        }\n        return build(loc_, len_);\n    }\n\n    // ════════════════════════════════════════════ CLONING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to the new memory.\n     * @param memView       The memory view\n     * @return arr          The cloned byte array\n     */\n    function clone(MemView memView) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        unchecked {\n            _unsafeCopyTo(memView, ptr + 0x20);\n        }\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 len_ = memView.len();\n        uint256 footprint_ = memView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    /**\n     * @notice Copies all views, joins them into a new bytearray.\n     * @param memViews      The memory views\n     * @return arr          The new byte array with joined data behind the given views\n     */\n    function join(MemView[] memory memViews) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        MemView newView;\n        unchecked {\n            newView = _unsafeJoin(memViews, ptr + 0x20);\n        }\n        uint256 len_ = newView.len();\n        uint256 footprint_ = newView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    // ══════════════════════════════════════════ INSPECTING MEMORY VIEW ═══════════════════════════════════════════════\n\n    /**\n     * @notice Returns the memory address of the underlying bytes.\n     * @param memView       The memory view\n     * @return loc_         The memory address\n     */\n    function loc(MemView memView) internal pure returns (uint256 loc_) {\n        // loc is stored in the highest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u003e\u003e 128;\n    }\n\n    /**\n     * @notice Returns the number of bytes of the view.\n     * @param memView       The memory view\n     * @return len_         The length of the view\n     */\n    function len(MemView memView) internal pure returns (uint256 len_) {\n        // len is stored in the lowest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u0026 type(uint128).max;\n    }\n\n    /**\n     * @notice Returns the endpoint of `memView`.\n     * @param memView       The memory view\n     * @return end_         The endpoint of `memView`\n     */\n    function end(MemView memView) internal pure returns (uint256 end_) {\n        // The endpoint never overflows uint128, let alone uint256, so we could use unchecked math here\n        unchecked {\n            return memView.loc() + memView.len();\n        }\n    }\n\n    /**\n     * @notice Returns the number of memory words this memory view occupies, rounded up.\n     * @param memView       The memory view\n     * @return words_       The number of memory words\n     */\n    function words(MemView memView) internal pure returns (uint256 words_) {\n        // returning ceil(length / 32.0)\n        unchecked {\n            return (memView.len() + 31) \u003e\u003e 5;\n        }\n    }\n\n    /**\n     * @notice Returns the in-memory footprint of a fresh copy of the view.\n     * @param memView       The memory view\n     * @return footprint_   The in-memory footprint of a fresh copy of the view.\n     */\n    function footprint(MemView memView) internal pure returns (uint256 footprint_) {\n        // words() * 32\n        return memView.words() \u003c\u003c 5;\n    }\n\n    // ════════════════════════════════════════════ HASHING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the keccak256 hash of the underlying memory\n     * @param memView       The memory view\n     * @return digest       The keccak256 hash of the underlying memory\n     */\n    function keccak(MemView memView) internal pure returns (bytes32 digest) {\n        uint256 loc_ = memView.loc();\n        uint256 len_ = memView.len();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            digest := keccak256(loc_, len_)\n        }\n    }\n\n    /**\n     * @notice Adds a salt to the keccak256 hash of the underlying data and returns the keccak256 hash of the\n     * resulting data.\n     * @param memView       The memory view\n     * @return digestSalted keccak256(salt, keccak256(memView))\n     */\n    function keccakSalted(MemView memView, bytes32 salt) internal pure returns (bytes32 digestSalted) {\n        return keccak256(bytes.concat(salt, memView.keccak()));\n    }\n\n    // ════════════════════════════════════════════ SLICING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Safe slicing without memory modification.\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the given index\n     */\n    function slice(MemView memView, uint256 index_, uint256 len_) internal pure returns (MemView) {\n        uint256 loc_ = memView.loc();\n        // Ensure it doesn't overrun the view\n        if (loc_ + index_ + len_ \u003e memView.end()) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // loc_ + index_ \u003c= memView.end()\n            return build({loc_: loc_ + index_, len_: len_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing bytes from `index` to end(memView).\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @return The new view for the slice starting from the given index until the initial view endpoint\n     */\n    function sliceFrom(MemView memView, uint256 index_) internal pure returns (MemView) {\n        uint256 len_ = memView.len();\n        // Ensure it doesn't overrun the view\n        if (index_ \u003e len_) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // index_ \u003c= len_ =\u003e memView.loc() + index_ \u003c= memView.loc() + memView.len() == memView.end()\n            return build({loc_: memView.loc() + index_, len_: len_ - index_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the first `len` bytes.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the initial view beginning\n     */\n    function prefix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        return memView.slice({index_: 0, len_: len_});\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the last `len` byte.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length until the initial view endpoint\n     */\n    function postfix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        uint256 viewLen = memView.len();\n        // Ensure it doesn't overrun the view\n        if (len_ \u003e viewLen) {\n            revert ViewOverrun();\n        }\n        // Could do the unchecked math due to the check above\n        uint256 index_;\n        unchecked {\n            index_ = viewLen - len_;\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // len_ \u003c= memView.len() =\u003e memView.loc() \u003c= loc_ \u003c= memView.end()\n            return build({loc_: memView.loc() + viewLen - len_, len_: len_});\n        }\n    }\n\n    // ═══════════════════════════════════════════ INDEXING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Load up to 32 bytes from the view onto the stack.\n     * @dev Returns a bytes32 with only the `bytes_` HIGHEST bytes set.\n     * This can be immediately cast to a smaller fixed-length byte array.\n     * To automatically cast to an integer, use `indexUint`.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return result       The 32 byte result having only `bytes_` highest bytes set\n     */\n    function index(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (bytes32 result) {\n        if (bytes_ == 0) {\n            return bytes32(0);\n        }\n        // Can't load more than 32 bytes to the stack in one go\n        if (bytes_ \u003e 32) {\n            revert IndexedTooMuch();\n        }\n        // The last indexed byte should be within view boundaries\n        if (index_ + bytes_ \u003e memView.len()) {\n            revert ViewOverrun();\n        }\n        uint256 bitLength = bytes_ \u003c\u003c 3; // bytes_ * 8\n        uint256 loc_ = memView.loc();\n        // Get a mask with `bitLength` highest bits set\n        uint256 mask;\n        // 0x800...00 binary representation is 100...00\n        // sar stands for \"signed arithmetic shift\": https://en.wikipedia.org/wiki/Arithmetic_shift\n        // sar(N-1, 100...00) = 11...100..00, with exactly N highest bits set to 1\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            mask := sar(sub(bitLength, 1), 0x8000000000000000000000000000000000000000000000000000000000000000)\n        }\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load a full word using index offset, and apply mask to ignore non-relevant bytes\n            result := and(mload(add(loc_, index_)), mask)\n        }\n    }\n\n    /**\n     * @notice Parse an unsigned integer from the view at `index`.\n     * @dev Requires that the view have \u003e= `bytes_` bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return The unsigned integer\n     */\n    function indexUint(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (uint256) {\n        bytes32 indexedBytes = memView.index(index_, bytes_);\n        // `index()` returns left-aligned `bytes_`, while integers are right-aligned\n        // Shifting here to right-align with the full 32 bytes word: need to shift right `(32 - bytes_)` bytes\n        unchecked {\n            // memView.index() reverts when bytes_ \u003e 32, thus unchecked math\n            return uint256(indexedBytes) \u003e\u003e ((32 - bytes_) \u003c\u003c 3);\n        }\n    }\n\n    /**\n     * @notice Parse an address from the view at `index`.\n     * @dev Requires that the view have \u003e= 20 bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @return The address\n     */\n    function indexAddress(MemView memView, uint256 index_) internal pure returns (address) {\n        // index 20 bytes as `uint160`, and then cast to `address`\n        return address(uint160(memView.indexUint(index_, 20)));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns a memory view over the specified memory location\n    /// without checking if it points to unallocated memory.\n    function _unsafeBuildUnchecked(uint256 loc_, uint256 len_) private pure returns (MemView) {\n        // There is no scenario where loc or len would overflow uint128, so we omit this check.\n        // We use the highest 128 bits to encode the location and the lowest 128 bits to encode the length.\n        return MemView.wrap((loc_ \u003c\u003c 128) | len_);\n    }\n\n    /**\n     * @notice Copy the view to a location, return an unsafe memory reference\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memView       The memory view\n     * @param newLoc        The new location to copy the underlying view data\n     * @return The memory view over the unsafe memory with the copied underlying data\n     */\n    function _unsafeCopyTo(MemView memView, uint256 newLoc) private view returns (MemView) {\n        uint256 len_ = memView.len();\n        uint256 oldLoc = memView.loc();\n\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (newLoc \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        bool res;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // use the identity precompile (0x04) to copy\n            res := staticcall(gas(), 0x04, oldLoc, len_, newLoc, len_)\n        }\n        if (!res) revert PrecompileOutOfGas();\n        return _unsafeBuildUnchecked({loc_: newLoc, len_: len_});\n    }\n\n    /**\n     * @notice Join the views in memory, return an unsafe reference to the memory.\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memViews      The memory views\n     * @return The conjoined view pointing to the new memory\n     */\n    function _unsafeJoin(MemView[] memory memViews, uint256 location) private view returns (MemView) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (location \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        // Copy the views to the specified location one by one, by tracking the amount of copied bytes so far\n        uint256 offset = 0;\n        for (uint256 i = 0; i \u003c memViews.length;) {\n            MemView memView = memViews[i];\n            // We can use the unchecked math here as location + sum(view.length) will never overflow uint256\n            unchecked {\n                _unsafeCopyTo(memView, location + offset);\n                offset += memView.len();\n                ++i;\n            }\n        }\n        return _unsafeBuildUnchecked({loc_: location, len_: offset});\n    }\n}\n\n// contracts/libs/merkle/MerkleMath.sol\n\nlibrary MerkleMath {\n    // ═════════════════════════════════════════ BASIC MERKLE CALCULATIONS ═════════════════════════════════════════════\n\n    /**\n     * @notice Calculates the merkle root for the given leaf and merkle proof.\n     * @dev Will revert if proof length exceeds the tree height.\n     * @param index     Index of `leaf` in tree\n     * @param leaf      Leaf of the merkle tree\n     * @param proof     Proof of inclusion of `leaf` in the tree\n     * @param height    Height of the merkle tree\n     * @return root_    Calculated Merkle Root\n     */\n    function proofRoot(uint256 index, bytes32 leaf, bytes32[] memory proof, uint256 height)\n        internal\n        pure\n        returns (bytes32 root_)\n    {\n        // Proof length could not exceed the tree height\n        uint256 proofLen = proof.length;\n        if (proofLen \u003e height) revert TreeHeightTooLow();\n        root_ = leaf;\n        /// @dev Apply unchecked to all ++h operations\n        unchecked {\n            // Go up the tree levels from the leaf following the proof\n            for (uint256 h = 0; h \u003c proofLen; ++h) {\n                // Get a sibling node on current level: this is proof[h]\n                root_ = getParent(root_, proof[h], index, h);\n            }\n            // Go up to the root: the remaining siblings are EMPTY\n            for (uint256 h = proofLen; h \u003c height; ++h) {\n                root_ = getParent(root_, bytes32(0), index, h);\n            }\n        }\n    }\n\n    /**\n     * @notice Calculates the parent of a node on the path from one of the leafs to root.\n     * @param node          Node on a path from tree leaf to root\n     * @param sibling       Sibling for a given node\n     * @param leafIndex     Index of the tree leaf\n     * @param nodeHeight    \"Level height\" for `node` (ZERO for leafs, ORIGIN_TREE_HEIGHT for root)\n     */\n    function getParent(bytes32 node, bytes32 sibling, uint256 leafIndex, uint256 nodeHeight)\n        internal\n        pure\n        returns (bytes32 parent)\n    {\n        // Index for `node` on its \"tree level\" is (leafIndex / 2**height)\n        // \"Left child\" has even index, \"right child\" has odd index\n        if ((leafIndex \u003e\u003e nodeHeight) \u0026 1 == 0) {\n            // Left child\n            return getParent(node, sibling);\n        } else {\n            // Right child\n            return getParent(sibling, node);\n        }\n    }\n\n    /// @notice Calculates the parent of tow nodes in the merkle tree.\n    /// @dev We use implementation with H(0,0) = 0\n    /// This makes EVERY empty node in the tree equal to ZERO,\n    /// saving us from storing H(0,0), H(H(0,0), H(0, 0)), and so on\n    /// @param leftChild    Left child of the calculated node\n    /// @param rightChild   Right child of the calculated node\n    /// @return parent      Value for the node having above mentioned children\n    function getParent(bytes32 leftChild, bytes32 rightChild) internal pure returns (bytes32 parent) {\n        if (leftChild == bytes32(0) \u0026\u0026 rightChild == bytes32(0)) {\n            return 0;\n        } else {\n            return keccak256(bytes.concat(leftChild, rightChild));\n        }\n    }\n\n    // ════════════════════════════════ ROOT/PROOF CALCULATION FOR A LIST OF LEAFS ═════════════════════════════════════\n\n    /**\n     * @notice Calculates merkle root for a list of given leafs.\n     * Merkle Tree is constructed by padding the list with ZERO values for leafs until list length is `2**height`.\n     * Merkle Root is calculated for the constructed tree, and then saved in `leafs[0]`.\n     * \u003e Note:\n     * \u003e - `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * \u003e - Caller is expected not to reuse `hashes` list after the call, and only use `leafs[0]` value,\n     * which is guaranteed to contain the calculated merkle root.\n     * \u003e - root is calculated using the `H(0,0) = 0` Merkle Tree implementation. See MerkleTree.sol for details.\n     * @dev Amount of leaves should be at most `2**height`\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param height    Height of the Merkle Tree to construct\n     */\n    function calculateRoot(bytes32[] memory hashes, uint256 height) internal pure {\n        uint256 levelLength = hashes.length;\n        // Amount of hashes could not exceed amount of leafs in tree with the given height\n        if (levelLength \u003e (1 \u003c\u003c height)) revert TreeHeightTooLow();\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\": the amount of iterations for the for loop above.\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n            }\n        }\n    }\n\n    /**\n     * @notice Generates a proof of inclusion of a leaf in the list. If the requested index is outside\n     * of the list range, generates a proof of inclusion for an empty leaf (proof of non-inclusion).\n     * The Merkle Tree is constructed by padding the list with ZERO values until list length is a power of two\n     * __AND__ index is in the extended list range. For example:\n     *  - `hashes.length == 6` and `0 \u003c= index \u003c= 7` will \"extend\" the list to 8 entries.\n     *  - `hashes.length == 6` and `7 \u003c index \u003c= 15` will \"extend\" the list to 16 entries.\n     * \u003e Note: `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * Caller is expected not to reuse `hashes` list after the call.\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param index     Leaf index to generate the proof for\n     * @return proof    Generated merkle proof\n     */\n    function calculateProof(bytes32[] memory hashes, uint256 index) internal pure returns (bytes32[] memory proof) {\n        // Use only meaningful values for the shortened proof\n        // Check if index is within the list range (we want to generates proofs for outside leafs as well)\n        uint256 height = getHeight(index \u003c hashes.length ? hashes.length : (index + 1));\n        proof = new bytes32[](height);\n        uint256 levelLength = hashes.length;\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Use sibling for the merkle proof; `index^1` is index of our sibling\n                proof[h] = (index ^ 1 \u003c levelLength) ? hashes[index ^ 1] : bytes32(0);\n\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\"\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n                // Traverse to parent node\n                index \u003e\u003e= 1;\n            }\n        }\n    }\n\n    /// @notice Returns the height of the tree having a given amount of leafs.\n    function getHeight(uint256 leafs) internal pure returns (uint256 height) {\n        uint256 amount = 1;\n        while (amount \u003c leafs) {\n            unchecked {\n                ++height;\n            }\n            amount \u003c\u003c= 1;\n        }\n    }\n}\n\n// contracts/libs/stack/GasData.sol\n\n/// GasData in encoded data with \"basic information about gas prices\" for some chain.\ntype GasData is uint96;\n\nusing GasDataLib for GasData global;\n\n/// ChainGas is encoded data with given chain's \"basic information about gas prices\".\ntype ChainGas is uint128;\n\nusing GasDataLib for ChainGas global;\n\n/// Library for encoding and decoding GasData and ChainGas structs.\n/// # GasData\n/// `GasData` is a struct to store the \"basic information about gas prices\", that could\n/// be later used to approximate the cost of a message execution, and thus derive the\n/// minimal tip values for sending a message to the chain.\n/// \u003e - `GasData` is supposed to be cached by `GasOracle` contract, allowing to store the\n/// \u003e approximates instead of the exact values, and thus save on storage costs.\n/// \u003e - For instance, if `GasOracle` only updates the values on +- 10% change, having an\n/// \u003e 0.4% error on the approximates would be acceptable.\n/// `GasData` is supposed to be included in the Origin's state, which are synced across\n/// chains using Agent-signed snapshots and attestations.\n/// ## GasData stack layout (from highest bits to lowest)\n///\n/// | Position   | Field        | Type   | Bytes | Description                                         |\n/// | ---------- | ------------ | ------ | ----- | --------------------------------------------------- |\n/// | (012..010] | gasPrice     | uint16 | 2     | Gas price for the chain (in Wei per gas unit)       |\n/// | (010..008] | dataPrice    | uint16 | 2     | Calldata price (in Wei per byte of content)         |\n/// | (008..006] | execBuffer   | uint16 | 2     | Tx fee safety buffer for message execution (in Wei) |\n/// | (006..004] | amortAttCost | uint16 | 2     | Amortized cost for attestation submission (in Wei)  |\n/// | (004..002] | etherPrice   | uint16 | 2     | Chain's Ether Price / Mainnet Ether Price (in BWAD) |\n/// | (002..000] | markup       | uint16 | 2     | Markup for the message execution (in BWAD)          |\n/// \u003e See Number.sol for more details on `Number` type and BWAD (binary WAD) math.\n///\n/// ## ChainGas stack layout (from highest bits to lowest)\n///\n/// | Position   | Field   | Type   | Bytes | Description      |\n/// | ---------- | ------- | ------ | ----- | ---------------- |\n/// | (016..004] | gasData | uint96 | 12    | Chain's gas data |\n/// | (004..000] | domain  | uint32 | 4     | Chain's domain   |\nlibrary GasDataLib {\n    /// @dev Amount of bits to shift to gasPrice field\n    uint96 private constant SHIFT_GAS_PRICE = 10 * 8;\n    /// @dev Amount of bits to shift to dataPrice field\n    uint96 private constant SHIFT_DATA_PRICE = 8 * 8;\n    /// @dev Amount of bits to shift to execBuffer field\n    uint96 private constant SHIFT_EXEC_BUFFER = 6 * 8;\n    /// @dev Amount of bits to shift to amortAttCost field\n    uint96 private constant SHIFT_AMORT_ATT_COST = 4 * 8;\n    /// @dev Amount of bits to shift to etherPrice field\n    uint96 private constant SHIFT_ETHER_PRICE = 2 * 8;\n\n    /// @dev Amount of bits to shift to gasData field\n    uint128 private constant SHIFT_GAS_DATA = 4 * 8;\n\n    // ═════════════════════════════════════════════════ GAS DATA ══════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded GasData struct with the given fields.\n    /// @param gasPrice_        Gas price for the chain (in Wei per gas unit)\n    /// @param dataPrice_       Calldata price (in Wei per byte of content)\n    /// @param execBuffer_      Tx fee safety buffer for message execution (in Wei)\n    /// @param amortAttCost_    Amortized cost for attestation submission (in Wei)\n    /// @param etherPrice_      Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n    /// @param markup_          Markup for the message execution (in BWAD)\n    function encodeGasData(\n        Number gasPrice_,\n        Number dataPrice_,\n        Number execBuffer_,\n        Number amortAttCost_,\n        Number etherPrice_,\n        Number markup_\n    ) internal pure returns (GasData) {\n        // Number type wraps uint16, so could safely be casted to uint96\n        // forgefmt: disable-next-item\n        return GasData.wrap(\n            uint96(Number.unwrap(gasPrice_)) \u003c\u003c SHIFT_GAS_PRICE |\n            uint96(Number.unwrap(dataPrice_)) \u003c\u003c SHIFT_DATA_PRICE |\n            uint96(Number.unwrap(execBuffer_)) \u003c\u003c SHIFT_EXEC_BUFFER |\n            uint96(Number.unwrap(amortAttCost_)) \u003c\u003c SHIFT_AMORT_ATT_COST |\n            uint96(Number.unwrap(etherPrice_)) \u003c\u003c SHIFT_ETHER_PRICE |\n            uint96(Number.unwrap(markup_))\n        );\n    }\n\n    /// @notice Wraps padded uint256 value into GasData struct.\n    function wrapGasData(uint256 paddedGasData) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(paddedGasData));\n    }\n\n    /// @notice Returns the gas price, in Wei per gas unit.\n    function gasPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_GAS_PRICE));\n    }\n\n    /// @notice Returns the calldata price, in Wei per byte of content.\n    function dataPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_DATA_PRICE));\n    }\n\n    /// @notice Returns the tx fee safety buffer for message execution, in Wei.\n    function execBuffer(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_EXEC_BUFFER));\n    }\n\n    /// @notice Returns the amortized cost for attestation submission, in Wei.\n    function amortAttCost(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_AMORT_ATT_COST));\n    }\n\n    /// @notice Returns the ratio of Chain's Ether Price / Mainnet Ether Price, in BWAD math.\n    function etherPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_ETHER_PRICE));\n    }\n\n    /// @notice Returns the markup for the message execution, in BWAD math.\n    function markup(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data)));\n    }\n\n    // ════════════════════════════════════════════════ CHAIN DATA ═════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded ChainGas struct with the given fields.\n    /// @param gasData_ Chain's gas data\n    /// @param domain_  Chain's domain\n    function encodeChainGas(GasData gasData_, uint32 domain_) internal pure returns (ChainGas) {\n        // GasData type wraps uint96, so could safely be casted to uint128\n        return ChainGas.wrap(uint128(GasData.unwrap(gasData_)) \u003c\u003c SHIFT_GAS_DATA | uint128(domain_));\n    }\n\n    /// @notice Wraps padded uint256 value into ChainGas struct.\n    function wrapChainGas(uint256 paddedChainGas) internal pure returns (ChainGas) {\n        // Casting to uint128 will truncate the highest bits, which is the behavior we want\n        return ChainGas.wrap(uint128(paddedChainGas));\n    }\n\n    /// @notice Returns the chain's gas data.\n    function gasData(ChainGas data) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(ChainGas.unwrap(data) \u003e\u003e SHIFT_GAS_DATA));\n    }\n\n    /// @notice Returns the chain's domain.\n    function domain(ChainGas data) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(ChainGas.unwrap(data));\n    }\n\n    /// @notice Returns the hash for the list of ChainGas structs.\n    function snapGasHash(ChainGas[] memory snapGas) internal pure returns (bytes32 snapGasHash_) {\n        // Use assembly to calculate the hash of the array without copying it\n        // ChainGas takes a single word of storage, thus ChainGas[] is stored in the following way:\n        // 0x00: length of the array, in words\n        // 0x20: first ChainGas struct\n        // 0x40: second ChainGas struct\n        // And so on...\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Find the location where the array data starts, we add 0x20 to skip the length field\n            let loc := add(snapGas, 0x20)\n            // Load the length of the array (in words).\n            // Shifting left 5 bits is equivalent to multiplying by 32: this converts from words to bytes.\n            let len := shl(5, mload(snapGas))\n            // Calculate the hash of the array\n            snapGasHash_ := keccak256(loc, len)\n        }\n    }\n}\n\n// contracts/libs/stack/Header.sol\n\n/// Header is encoded data with \"general routing information\".\ntype Header is uint136;\n\nusing HeaderLib for Header global;\n\n/// Types of messages supported by Origin-Destination\n/// - Base: message sent by protocol user, contains tips\n/// - Manager: message sent between AgentManager contracts located on different chains, no tips\nenum MessageFlag {\n    Base,\n    Manager\n}\n\nusing HeaderLib for MessageFlag global;\n\n/// Library for formatting _the header part_ of _the messages used by Origin and Destination_.\n/// - Header represents general information for routing a Message for Origin and Destination.\n/// - Header occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n///\n/// # Header stack layout (from highest bits to lowest)\n///\n/// | Position   | Field            | Type   | Bytes | Description                             |\n/// | ---------- | ---------------- | ------ | ----- | --------------------------------------- |\n/// | (017..016] | flag             | uint8  | 1     | Flag specifying the type of message     |\n/// | (016..012] | origin           | uint32 | 4     | Domain where message originated         |\n/// | (012..008] | nonce            | uint32 | 4     | Message nonce on the origin domain      |\n/// | (008..004] | destination      | uint32 | 4     | Domain where message will be executed   |\n/// | (004..000] | optimisticPeriod | uint32 | 4     | Optimistic period that will be enforced |\nlibrary HeaderLib {\n    /// @dev Amount of bits to shift to flag field\n    uint136 private constant SHIFT_FLAG = 16 * 8;\n    /// @dev Amount of bits to shift to origin field\n    uint136 private constant SHIFT_ORIGIN = 12 * 8;\n    /// @dev Amount of bits to shift to nonce field\n    uint136 private constant SHIFT_NONCE = 8 * 8;\n    /// @dev Amount of bits to shift to destination field\n    uint136 private constant SHIFT_DESTINATION = 4 * 8;\n\n    /// @notice Returns an encoded header with provided fields\n    /// @param origin_              Domain of origin chain\n    /// @param nonce_               Message nonce on origin chain\n    /// @param destination_         Domain of destination chain\n    /// @param optimisticPeriod_    Optimistic period for message execution\n    function encodeHeader(\n        MessageFlag flag_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint32 destination_,\n        uint32 optimisticPeriod_\n    ) internal pure returns (Header) {\n        // All casts below are upcasts, so they are safe\n        // forgefmt: disable-next-item\n        return Header.wrap(\n            uint136(uint8(flag_)) \u003c\u003c SHIFT_FLAG |\n            uint136(origin_) \u003c\u003c SHIFT_ORIGIN |\n            uint136(nonce_) \u003c\u003c SHIFT_NONCE |\n            uint136(destination_) \u003c\u003c SHIFT_DESTINATION |\n            uint136(optimisticPeriod_)\n        );\n    }\n\n    /// @notice Checks that the header is a valid encoded header.\n    function isHeader(uint256 paddedHeader) internal pure returns (bool) {\n        // Check that flag is within range\n        return _flag(paddedHeader) \u003c= uint8(type(MessageFlag).max);\n    }\n\n    /// @notice Wraps the padded encoded request into a Header-typed value.\n    /// @dev The \"padded\" header is simply an encoded header casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded headers\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedHeader) internal pure returns (Header) {\n        // Check that flag is within range\n        if (!isHeader(paddedHeader)) revert FlagOutOfRange();\n        // Casting to uint136 will truncate the highest bits, which is the behavior we want\n        return Header.wrap(uint136(paddedHeader));\n    }\n\n    /// @notice Returns header's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Header header) internal pure returns (bytes32 hashedHeader) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store header in scratch space\n            mstore(0, header)\n            // Compute hash of header padded to 32 bytes\n            hashedHeader := keccak256(0, 32)\n        }\n    }\n\n    // ══════════════════════════════════════════════ HEADER SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns header's flag field\n    function flag(Header header) internal pure returns (MessageFlag) {\n        // We check that flag is within range when wrapping the header, so this cast is safe\n        return MessageFlag(_flag(Header.unwrap(header)));\n    }\n\n    /// @notice Returns header's origin field\n    function origin(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_ORIGIN);\n    }\n\n    /// @notice Returns header's nonce field\n    function nonce(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_NONCE);\n    }\n\n    /// @notice Returns header's destination field\n    function destination(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_DESTINATION);\n    }\n\n    /// @notice Returns header's optimistic seconds field\n    function optimisticPeriod(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns header's flag field without casting to MessageFlag\n    function _flag(uint256 paddedHeader) private pure returns (uint8) {\n        // Casting to uint8 will truncate the highest bits, which is the behavior we want\n        return uint8(paddedHeader \u003e\u003e SHIFT_FLAG);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n     * constructor.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall \u0026\u0026 _initialized \u003c 1) || (!AddressUpgradeable.isContract(address(this)) \u0026\u0026 _initialized == 1),\n            \"Initializable: contract is already initialized\"\n        );\n        _initialized = 1;\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: setting the version to 255 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing \u0026\u0026 _initialized \u003c version, \"Initializable: contract is already initialized\");\n        _initialized = version;\n        _initializing = true;\n        _;\n        _initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        require(_initializing, \"Initializable: contract is not initializing\");\n        _;\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized != type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint8) {\n        return _initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _initializing;\n    }\n}\n\n// contracts/interfaces/IAgentManager.sol\n\ninterface IAgentManager {\n    /**\n     * @notice Allows Inbox to open a Dispute between a Guard and a Notary, if they are both not in Dispute already.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Guard or Notary is already in Dispute.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Allows Inbox to slash an agent, if their fraud was proven.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Domain doesn't match the saved agent domain.\n     * @param domain    Domain where the Agent is active\n     * @param agent     Address of the Agent\n     * @param prover    Address that initially provided fraud proof\n     */\n    function slashAgent(uint32 domain, address agent, address prover) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest known root of the Agent Merkle Tree.\n     */\n    function agentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns the number of opened Disputes.\n     * @dev This includes the Disputes that have been resolved already.\n     */\n    function getDisputesAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns information about the dispute with the given index.\n     * @dev Will revert if dispute with given index hasn't been opened yet.\n     * @param index             Dispute index\n     * @return guard            Address of the Guard in the Dispute\n     * @return notary           Address of the Notary in the Dispute\n     * @return slashedAgent     Address of the Agent who was slashed when Dispute was resolved\n     * @return fraudProver      Address who provided fraud proof to resolve the Dispute\n     * @return reportPayload    Raw payload with report data that led to the Dispute\n     * @return reportSignature  Guard signature for the report payload\n     */\n    function getDispute(uint256 index)\n        external\n        view\n        returns (\n            address guard,\n            address notary,\n            address slashedAgent,\n            address fraudProver,\n            bytes memory reportPayload,\n            bytes memory reportSignature\n        );\n\n    /**\n     * @notice Returns the current Dispute status of a given agent. See Structures.sol for details.\n     * @dev Every returned value will be set to zero if agent was not slashed and is not in Dispute.\n     * `rival` and `disputePtr` will be set to zero if the agent was slashed without being in Dispute.\n     * @param agent         Agent address\n     * @return flag         Flag describing the current Dispute status for the agent: None/Pending/Slashed\n     * @return rival        Address of the rival agent in the Dispute\n     * @return fraudProver  Address who provided fraud proof to resolve the Dispute\n     * @return disputePtr   Index of the opened Dispute PLUS ONE. Zero if agent is not in Dispute.\n     */\n    function disputeStatus(address agent)\n        external\n        view\n        returns (DisputeFlag flag, address rival, address fraudProver, uint256 disputePtr);\n}\n\n// contracts/interfaces/IAgentSecured.sol\n\ninterface IAgentSecured {\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * between a Guard and a Notary has been opened.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * has been resolved due to one of the agents being slashed.\n     * \u003e `rivalIndex` will be ZERO, if the slashed agent was not in the Dispute.\n     * @param slashedIndex  Index of the slashed agent in the Agent Merkle Tree\n     * @param rivalIndex    Index of the their Dispute Rival in the Agent Merkle Tree\n     */\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the address of the local AgentManager contract, which is treated as\n     * the \"source of truth\" for agent statuses.\n     */\n    function agentManager() external view returns (address);\n\n    /**\n     * @notice Returns the address of the local Inbox contract, which is treated as\n     * the \"source of truth\" for agent-signed statements.\n     * @dev Inbox passes verified agent statements to `IAgentSecured` contract.\n     */\n    function inbox() external view returns (address);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns (flag, openedAt, resolvedAt) that describes the latest status of\n     * the latest dispute for an agent with a given index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param agentIndex    Agent index in the Agent Merkle Tree\n     * @return              Latest dispute status for the given agent: (flag, openedAt, resolvedAt)\n     */\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory);\n}\n\n// contracts/libs/memory/ByteString.sol\n\n/// @dev CallData is a memory view over the payload to be used for an external call, i.e.\n/// recipient.call(callData). Its length is always (4 + 32 * N) bytes:\n/// - First 4 bytes represent the function selector.\n/// - 32 * N bytes represent N words that function arguments occupy.\ntype CallData is uint256;\n\n/// @dev Attach library functions to CallData\nusing ByteString for CallData global;\n\n/// @dev Signature is a memory view over a \"65 bytes\" array representing a ECDSA signature.\ntype Signature is uint256;\n\n/// @dev Attach library functions to Signature\nusing ByteString for Signature global;\n\nlibrary ByteString {\n    using MemViewLib for bytes;\n\n    /**\n     * @dev non-compact ECDSA signatures are enforced as of OZ 4.7.3\n     *\n     *      Signature payload memory layout\n     * [000 .. 032) r   bytes32 32 bytes\n     * [032 .. 064) s   bytes32 32 bytes\n     * [064 .. 065) v   uint8    1 byte\n     */\n    uint256 internal constant SIGNATURE_LENGTH = 65;\n    uint256 private constant OFFSET_R = 0;\n    uint256 private constant OFFSET_S = 32;\n    uint256 private constant OFFSET_V = 64;\n\n    /**\n     * @dev Calldata memory layout\n     * [000 .. 004) selector    bytes4  4 bytes\n     *      Optional: N function arguments\n     * [004 .. 036) arg1        bytes32 32 bytes\n     *      ..\n     * [AAA .. END) argN        bytes32 32 bytes\n     */\n    uint256 internal constant SELECTOR_LENGTH = 4;\n    uint256 private constant OFFSET_SELECTOR = 0;\n    uint256 private constant OFFSET_ARGUMENTS = SELECTOR_LENGTH;\n\n    // ═════════════════════════════════════════════════ SIGNATURE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the signature payload from the given values.\n     * @dev Using ByteString.formatSignature({r: r, s: s, v: v}) will make sure\n     * that params are given in the right order.\n     */\n    function formatSignature(bytes32 r, bytes32 s, uint8 v) internal pure returns (bytes memory) {\n        return abi.encodePacked(r, s, v);\n    }\n\n    /**\n     * @notice Returns a Signature view over for the given payload.\n     * @dev Will revert if the payload is not a signature.\n     */\n    function castToSignature(bytes memory payload) internal pure returns (Signature) {\n        return castToSignature(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Signature view.\n     * @dev Will revert if the memory view is not over a signature.\n     */\n    function castToSignature(MemView memView) internal pure returns (Signature) {\n        if (!isSignature(memView)) revert UnformattedSignature();\n        return Signature.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a signature\n     */\n    function isSignature(MemView memView) internal pure returns (bool) {\n        return memView.len() == SIGNATURE_LENGTH;\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Signature signature) internal pure returns (MemView) {\n        return MemView.wrap(Signature.unwrap(signature));\n    }\n\n    // ═════════════════════════════════════════════ SIGNATURE SLICING ═════════════════════════════════════════════════\n\n    /// @notice Unpacks signature payload into (r, s, v) parameters.\n    /// @dev Make sure to verify signature length with isSignature() beforehand.\n    function toRSV(Signature signature) internal pure returns (bytes32 r, bytes32 s, uint8 v) {\n        // Get the underlying memory view\n        MemView memView = unwrap(signature);\n        r = memView.index({index_: OFFSET_R, bytes_: 32});\n        s = memView.index({index_: OFFSET_S, bytes_: 32});\n        // Can be safely casted to uint8, since we index a single byte\n        v = uint8(memView.indexUint({index_: OFFSET_V, bytes_: 1}));\n    }\n\n    // ═════════════════════════════════════════════════ CALLDATA ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the calldata with the modified arguments:\n     * the existing arguments are prepended with the arguments from the prefix.\n     * @dev Given:\n     *  - `calldata = abi.encodeWithSelector(foo.selector, d, e);`\n     *  - `prefix = abi.encode(a, b, c);`\n     *  - `a`, `b`, `c` are arguments of static type (i.e. not dynamically sized ones)\n     *      Then:\n     *  - Function will return abi.encodeWithSelector(foo.selector, a, c, c, d, e)\n     *  - Returned calldata will trigger `foo(a, b, c, d, e)` when used for a contract call.\n     * Note: for clarification as to what types are considered static, see\n     * https://docs.soliditylang.org/en/latest/abi-spec.html#formal-specification-of-the-encoding\n     * @param callData  Calldata that needs to be modified\n     * @param prefix    ABI-encoded arguments to use as the first arguments in the new calldata\n     * @return Modified calldata having prefix as the first arguments.\n     */\n    function addPrefix(CallData callData, bytes memory prefix) internal view returns (bytes memory) {\n        // Prefix should occupy a whole amount of words in memory\n        if (!_fullWords(prefix.length)) revert UnformattedCallDataPrefix();\n        MemView[] memory views = new MemView[](3);\n        // Use payload's function selector\n        views[0] = abi.encodePacked(callData.callSelector()).ref();\n        // Use prefix as the first arguments\n        views[1] = prefix.ref();\n        // Use payload's remaining arguments\n        views[2] = callData.arguments();\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a CallData view over for the given payload.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(bytes memory payload) internal pure returns (CallData) {\n        return castToCallData(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a CallData view.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(MemView memView) internal pure returns (CallData) {\n        if (!isCallData(memView)) revert UnformattedCallData();\n        return CallData.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a valid calldata, i.e.\n     * a function selector, followed by arbitrary amount of arguments.\n     */\n    function isCallData(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Calldata should at least have a function selector\n        if (length \u003c SELECTOR_LENGTH) return false;\n        // The remainder of the calldata should be exactly N memory words (N \u003e= 0)\n        return _fullWords(length - SELECTOR_LENGTH);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(CallData callData) internal pure returns (MemView) {\n        return MemView.wrap(CallData.unwrap(callData));\n    }\n\n    /// @notice Returns callData's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(CallData callData) internal pure returns (bytes32) {\n        return callData.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ CALLDATA SLICING ══════════════════════════════════════════════════\n\n    /**\n     * @notice Returns amount of memory words (32 byte chunks) the function arguments\n     * occupy in the calldata.\n     * @dev This might differ from amount of arguments supplied, if any of the arguments\n     * occupies more than one memory slot. It is true, however, that argument part of the payload\n     * occupies exactly N words, even for dynamic types like `bytes`\n     */\n    function argumentWords(CallData callData) internal pure returns (uint256) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        // Equivalent of (length - SELECTOR_LENGTH) / 32\n        return (memView.len() - SELECTOR_LENGTH) \u003e\u003e 5;\n    }\n\n    /// @notice Returns selector for the provided calldata.\n    function callSelector(CallData callData) internal pure returns (bytes4) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return bytes4(memView.index({index_: OFFSET_SELECTOR, bytes_: SELECTOR_LENGTH}));\n    }\n\n    /// @notice Returns abi encoded arguments for the provided calldata.\n    function arguments(CallData callData) internal pure returns (MemView) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return memView.sliceFrom({index_: OFFSET_ARGUMENTS});\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if length is full amount of memory words (32 bytes).\n    function _fullWords(uint256 length) internal pure returns (bool) {\n        // The equivalent of length % 32 == 0\n        return length \u0026 31 == 0;\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n    function __Context_init() internal onlyInitializing {\n    }\n\n    function __Context_init_unchained() internal onlyInitializing {\n    }\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[50] private __gap;\n}\n\n// contracts/libs/merkle/MerkleTree.sol\n\n/// `BaseTree` is a struct representing incremental merkle tree.\n/// - Contains only the current branch.\n/// - The number of inserted leaves is stored externally, and is later supplied for tree operations.\n/// - Has a fixed height of `ORIGIN_TREE_HEIGHT`.\n/// - Can store up to `2 ** ORIGIN_TREE_HEIGHT - 1` leaves.\n/// \u003e Note: the hash function for the tree `H(x, y)` is defined as:\n/// \u003e - `H(0,0) = 0`\n/// \u003e - `H(x,y) = keccak256(x, y), when (x != 0 || y != 0)`\n/// ## Invariant for leafs\n/// - The leftmost empty leaf has `index == count`, where `count` is the amount of the inserted leafs so far.\n/// - Value for any empty leaf or node is bytes32(0).\n/// ## Invariant for current branch\n/// `branch[i]` is always the value of a node on the i-th level.\n/// Levels are numbered from leafs to root: `0 .. ORIGIN_TREE_HEIGHT`.\n/// `branch[i]` stores the value for the node, such that:\n//  - The node is a \"left child\" (e.g. has an even index).\n/// - The node must have two non-empty children.\n/// - Out of all level's \"left child\" nodes with \"non-empty children\",\n/// the one with the biggest index (the rightmost one) is stored as `branch[i]`.\n/// \u003e __`branch` could be used to form a proof of inclusion for the first empty leaf (`index == count`).__\n/// _Here is how:_\n/// - Let's walk along the path from the \"first empty leaf\" to the root.\n/// - i-th bit of the \"first empty leaf\" index (which is equal to `count`) determines if the path's node\n/// for this i-th level is a \"left child\" or a \"right child\".\n/// - i-th bit in `count` is 0 → we are the left child on this level → sibling is the right child\n/// that does not exist yet → `proof[i] = bytes32(0)`.\n/// - i-th bit in `count` is 1 → we are the right child on this level → sibling is the left child\n/// sibling is the rightmost \"left child\" node on the level → `proof[i] = branch[i]`.\n/// \u003e Therefore `proof[i] = (count \u0026 (1 \u003c\u003c i)) == 0 ? bytes32(0) : branch[i])`\nstruct BaseTree {\n    bytes32[ORIGIN_TREE_HEIGHT] branch;\n}\n\nusing MerkleTree for BaseTree global;\n\n/// `HistoricalTree` is an incremental merkle tree keeping track of its historical merkle roots.\n/// \u003e - `roots[N]` is the root of the tree after `N` leafs were inserted\n/// \u003e - `roots[0] == bytes32(0)`\n/// @param tree     Incremental merkle tree\n/// @param roots    Historical merkle roots of the tree\nstruct HistoricalTree {\n    BaseTree tree;\n    bytes32[] roots;\n}\n\nusing MerkleTree for HistoricalTree global;\n\n/// `DynamicTree` is a struct representing a Merkle Tree with `2**AGENT_TREE_HEIGHT` leaves.\n/// - A single operation is available: update value for leaf with an arbitrary index (which might be a non-empty leaf).\n/// - This is done by requesting the proof of inclusion for the old value, which is used to both\n/// verify the old value, and calculate the new root.\n/// \u003e Based on Original idea from [ER forum post](https://ethresear.ch/t/efficient-on-chain-dynamic-merkle-tree/11054).\nstruct DynamicTree {\n    bytes32 root;\n}\n\nusing MerkleTree for DynamicTree global;\n\n/// MerkleTree is work based on Nomad's Merkle.sol, which is used under MIT OR Apache-2.0\n/// [link](https://github.com/nomad-xyz/monorepo/blob/main/packages/contracts-core/contracts/libs/Merkle.sol).\n/// With the following changes:\n/// - Adapted for Solidity 0.8.x.\n/// - Amount of tree leaves stored externally.\n/// - Added thorough documentation.\n/// - `H(0,0) = 0` optimization from [ER forum post](https://ethresear.ch/t/optimizing-sparse-merkle-trees/3751/6).\n/// \u003e Nomad's Merkle.sol is work based on eth2 deposit contract, which is used under CC0-1.0\n///[link](https://github.com/ethereum/deposit_contract/blob/dev/deposit_contract/contracts/validator_registration.v.py).\n/// With the following changes:\n/// \u003e - Implemented in Solidity 0.7.6 (eth2 deposit contract implemented in Vyper).\n/// \u003e - `H() = keccak256()` is used as the hashing function instead of `sha256()`.\nlibrary MerkleTree {\n    /// @dev For root calculation we need at least one empty leaf, thus the minus one in the formula.\n    uint256 internal constant MAX_LEAVES = 2 ** ORIGIN_TREE_HEIGHT - 1;\n\n    // ═════════════════════════════════════════════════ BASE TREE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Inserts `node` into merkle tree\n     * @dev Reverts if tree is full\n     * @param newCount  Amount of inserted leaves in the tree after the insertion (i.e. current + 1)\n     * @param node      Element to insert into tree\n     */\n    function insertBase(BaseTree storage tree, uint256 newCount, bytes32 node) internal {\n        if (newCount \u003e MAX_LEAVES) revert MerkleTreeFull();\n        // We go up the tree following the branch from the empty leaf AFTER the just inserted one.\n        // We stop when we find the first \"right child\" node.\n        // Its sibling is now the rightmost \"left child\" node that has two non-empty children.\n        // Therefore we need to update `tree.branch` value on this level.\n        // One could see that `tree.branch` value on lower and higher levels remain unchanged.\n\n        // Loop invariant: `node` is the current level's value for the branch from JUST INSERTED leaf\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            if ((newCount \u0026 1) == 1) {\n                // Found the first \"right child\" node on the branch from EMPTY leaf\n                // `node` is the value for node on branch from JUST INSERTED leaf\n                // Which in this case is the \"left child\".\n                // We update tree.branch and exit\n                tree.branch[i] = node;\n                return;\n            }\n            // On the branch from EMPTY leaf this is still a \"left child\".\n            // Meaning on branch from JUST INSERTED leaf, `node` is a right child.\n            // We compute value for `node` parent using `tree.branch` invariant:\n            // This is the rightmost \"left child\" node, which would be sibling of `node`.\n            node = MerkleMath.getParent(tree.branch[i], node);\n            // Get the parent index, and go to the next tree level\n            newCount \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n        // As the loop should always end prematurely with the `return` statement,\n        // this code should be unreachable. We assert `false` just to be safe.\n        assert(false);\n    }\n\n    /**\n     * @notice Calculates and returns current root of the merkle tree.\n     * @param count     Current amount of inserted leaves in the tree\n     * @return current  Calculated root of `tree`\n     */\n    function rootBase(BaseTree storage tree, uint256 count) internal view returns (bytes32 current) {\n        // To calculate the root we follow the branch of first EMPTY leaf (index == count)\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            // Check if we are the left or the right child on the current level\n            if ((count \u0026 1) == 1) {\n                // We are the right child. Our sibling is the \"rightmost\" \"left-child\" node\n                // that has two non-empty children → sibling is `tree.branch[i]`\n                current = MerkleMath.getParent(tree.branch[i], current);\n            } else {\n                // We are the left child. Our sibling does not exist yet → sibling is EMPTY\n                current = MerkleMath.getParent(current, bytes32(0));\n            }\n            // Get the parent index, and go to the next tree level\n            count \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    // ══════════════════════════════════════════════ HISTORICAL TREE ══════════════════════════════════════════════════\n\n    /// @notice Initializes the historical roots for the tree by inserting an empty root.\n    // solhint-disable-next-line ordering\n    function initializeRoots(HistoricalTree storage tree) internal returns (bytes32 savedRoot) {\n        // This should only be called once, when the contract is initialized\n        assert(tree.roots.length == 0);\n        // Save root for empty merkle tree: bytes32(0)\n        tree.roots.push(savedRoot);\n    }\n\n    /// @notice Inserts a new leaf into the merkle tree.\n    /// @dev Reverts if tree is full.\n    /// @param node         Element to insert into tree\n    /// @return newRoot     Merkle root after the leaf was inserted\n    function insert(HistoricalTree storage tree, bytes32 node) internal returns (bytes32 newRoot) {\n        // Tree count after the new leaf will be inserted (we store roots[0] as root of empty tree)\n        uint256 newCount = tree.roots.length;\n        tree.tree.insertBase(newCount, node);\n        // Save the new root\n        newRoot = tree.tree.rootBase(newCount);\n        tree.roots.push(newRoot);\n    }\n\n    /// @notice Returns the historical root of the merkle tree.\n    /// @dev Reverts if not enough leafs have been inserted.\n    /// @param count            Amount of leafs in the tree at some point of time\n    /// @return historicalRoot  Merkle root after `count` leafs were inserted\n    function root(HistoricalTree storage tree, uint256 count) internal view returns (bytes32 historicalRoot) {\n        if (count \u003e= tree.roots.length) revert NotEnoughLeafs();\n        return tree.roots[count];\n    }\n\n    // ═══════════════════════════════════════════════ DYNAMIC TREE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Updates the value for the leaf with the given index in the Dynamic Merkle Tree.\n     * @dev Will revert if incorrect proof of inclusion for old value is supplied.\n     * @param tree          Dynamic merkle tree\n     * @param index         Index of the leaf to update\n     * @param oldValue      Previous value of the leaf\n     * @param branch        Proof of inclusion of previous value into the tree\n     * @param newValue      New leaf value to assign\n     * @return newRoot      New value for the Merkle Root after the leaf is updated\n     */\n    function update(\n        DynamicTree storage tree,\n        uint256 index,\n        bytes32 oldValue,\n        bytes32[] memory branch,\n        bytes32 newValue\n    ) internal returns (bytes32 newRoot) {\n        // Check that the old value + proof result in a correct root\n        if (MerkleMath.proofRoot(index, oldValue, branch, AGENT_TREE_HEIGHT) != tree.root) {\n            revert LeafNotProven();\n        }\n        // New root is new value + the same proof (values for sibling nodes are not updated)\n        newRoot = MerkleMath.proofRoot(index, newValue, branch, AGENT_TREE_HEIGHT);\n        // Write the new root\n        tree.root = newRoot;\n    }\n}\n\n// contracts/libs/stack/Tips.sol\n\n/// Tips is encoded data with \"tips paid for sending a base message\".\n/// Note: even though uint256 is also an underlying type for MemView, Tips is stored ON STACK.\ntype Tips is uint256;\n\nusing TipsLib for Tips global;\n\n/// # Tips\n/// Library for formatting _the tips part_ of _the base messages_.\n///\n/// ## How the tips are awarded\n/// Tips are paid for sending a base message, and are split across all the agents that\n/// made the message execution on destination chain possible.\n/// ### Summit tips\n/// Split between:\n///     - Guard posting a snapshot with state ST_G for the origin chain.\n///     - Notary posting a snapshot SN_N using ST_G. This creates attestation A.\n///     - Notary posting a message receipt after it is executed on destination chain.\n/// ### Attestation tips\n/// Paid to:\n///     - Notary posting attestation A to destination chain.\n/// ### Execution tips\n/// Paid to:\n///     - First executor performing a valid execution attempt (correct proofs, optimistic period over),\n///      using attestation A to prove message inclusion on origin chain, whether the recipient reverted or not.\n/// ### Delivery tips.\n/// Paid to:\n///     - Executor who successfully executed the message on destination chain.\n///\n/// ## Tips encoding\n/// - Tips occupy a single storage word, and thus are stored on stack instead of being stored in memory.\n/// - The actual tip values should be determined by multiplying stored values by divided by TIPS_MULTIPLIER=2**32.\n/// - Tips are packed into a single word of storage, while allowing real values up to ~8*10**28 for every tip category.\n/// \u003e The only downside is that the \"real tip values\" are now multiplies of ~4*10**9, which should be fine even for\n/// the chains with the most expensive gas currency.\n/// # Tips stack layout (from highest bits to lowest)\n///\n/// | Position   | Field          | Type   | Bytes | Description                                                |\n/// | ---------- | -------------- | ------ | ----- | ---------------------------------------------------------- |\n/// | (032..024] | summitTip      | uint64 | 8     | Tip for agents interacting with Summit contract            |\n/// | (024..016] | attestationTip | uint64 | 8     | Tip for Notary posting attestation to Destination contract |\n/// | (016..008] | executionTip   | uint64 | 8     | Tip for valid execution attempt on destination chain       |\n/// | (008..000] | deliveryTip    | uint64 | 8     | Tip for successful message delivery on destination chain   |\n\nlibrary TipsLib {\n    using SafeCast for uint256;\n\n    /// @dev Amount of bits to shift to summitTip field\n    uint256 private constant SHIFT_SUMMIT_TIP = 24 * 8;\n    /// @dev Amount of bits to shift to attestationTip field\n    uint256 private constant SHIFT_ATTESTATION_TIP = 16 * 8;\n    /// @dev Amount of bits to shift to executionTip field\n    uint256 private constant SHIFT_EXECUTION_TIP = 8 * 8;\n\n    // ═══════════════════════════════════════════════════ TIPS ════════════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips with the given fields\n    /// @param summitTip_        Tip for agents interacting with Summit contract, divided by TIPS_MULTIPLIER\n    /// @param attestationTip_   Tip for Notary posting attestation to Destination contract, divided by TIPS_MULTIPLIER\n    /// @param executionTip_     Tip for valid execution attempt on destination chain, divided by TIPS_MULTIPLIER\n    /// @param deliveryTip_      Tip for successful message delivery on destination chain, divided by TIPS_MULTIPLIER\n    function encodeTips(uint64 summitTip_, uint64 attestationTip_, uint64 executionTip_, uint64 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // forgefmt: disable-next-item\n        return Tips.wrap(\n            uint256(summitTip_) \u003c\u003c SHIFT_SUMMIT_TIP |\n            uint256(attestationTip_) \u003c\u003c SHIFT_ATTESTATION_TIP |\n            uint256(executionTip_) \u003c\u003c SHIFT_EXECUTION_TIP |\n            uint256(deliveryTip_)\n        );\n    }\n\n    /// @notice Convenience function to encode tips with uint256 values.\n    function encodeTips256(uint256 summitTip_, uint256 attestationTip_, uint256 executionTip_, uint256 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // In practice, the tips amounts are not supposed to be higher than 2**96, and with 32 bits of granularity\n        // using uint64 is enough to store the values. However, we still check for overflow just in case.\n        // TODO: consider using Number type to store the tips values.\n        return encodeTips({\n            summitTip_: (summitTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            attestationTip_: (attestationTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            executionTip_: (executionTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            deliveryTip_: (deliveryTip_ \u003e\u003e TIPS_GRANULARITY).toUint64()\n        });\n    }\n\n    /// @notice Wraps the padded encoded tips into a Tips-typed value.\n    /// @dev There is no actual padding here, as the underlying type is already uint256,\n    /// but we include this function for consistency and to be future-proof, if tips will eventually use anything\n    /// smaller than uint256.\n    function wrapPadded(uint256 paddedTips) internal pure returns (Tips) {\n        return Tips.wrap(paddedTips);\n    }\n\n    /**\n     * @notice Returns a formatted Tips payload specifying empty tips.\n     * @return Formatted tips\n     */\n    function emptyTips() internal pure returns (Tips) {\n        return Tips.wrap(0);\n    }\n\n    /// @notice Returns tips's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Tips tips) internal pure returns (bytes32 hashedTips) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store tips in scratch space\n            mstore(0, tips)\n            // Compute hash of tips padded to 32 bytes\n            hashedTips := keccak256(0, 32)\n        }\n    }\n\n    // ═══════════════════════════════════════════════ TIPS SLICING ════════════════════════════════════════════════════\n\n    /// @notice Returns summitTip field\n    function summitTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_SUMMIT_TIP);\n    }\n\n    /// @notice Returns attestationTip field\n    function attestationTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_ATTESTATION_TIP);\n    }\n\n    /// @notice Returns executionTip field\n    function executionTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_EXECUTION_TIP);\n    }\n\n    /// @notice Returns deliveryTip field\n    function deliveryTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips));\n    }\n\n    // ════════════════════════════════════════════════ TIPS VALUE ═════════════════════════════════════════════════════\n\n    /// @notice Returns total value of the tips payload.\n    /// This is the sum of the encoded values, scaled up by TIPS_MULTIPLIER\n    function value(Tips tips) internal pure returns (uint256 value_) {\n        value_ = uint256(tips.summitTip()) + tips.attestationTip() + tips.executionTip() + tips.deliveryTip();\n        value_ \u003c\u003c= TIPS_GRANULARITY;\n    }\n\n    /// @notice Increases the delivery tip to match the new value.\n    function matchValue(Tips tips, uint256 newValue) internal pure returns (Tips newTips) {\n        uint256 oldValue = tips.value();\n        if (newValue \u003c oldValue) revert TipsValueTooLow();\n        // We want to increase the delivery tip, while keeping the other tips the same\n        unchecked {\n            uint256 delta = (newValue - oldValue) \u003e\u003e TIPS_GRANULARITY;\n            // `delta` fits into uint224, as TIPS_GRANULARITY is 32, so this never overflows uint256.\n            // In practice, this will never overflow uint64 as well, but we still check it just in case.\n            if (delta + tips.deliveryTip() \u003e type(uint64).max) revert TipsOverflow();\n            // Delivery tips occupy lowest 8 bytes, so we can just add delta to the tips value\n            // to effectively increase the delivery tip (knowing that delta fits into uint64).\n            newTips = Tips.wrap(Tips.unwrap(tips) + delta);\n        }\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    function __Ownable_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable_init_unchained() internal onlyInitializing {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n    function __Ownable2Step_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable2Step_init_unchained() internal onlyInitializing {\n    }\n    address private _pendingOwner;\n\n    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Returns the address of the pending owner.\n     */\n    function pendingOwner() public view virtual returns (address) {\n        return _pendingOwner;\n    }\n\n    /**\n     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual override onlyOwner {\n        _pendingOwner = newOwner;\n        emit OwnershipTransferStarted(owner(), newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual override {\n        delete _pendingOwner;\n        super._transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev The new owner accepts the ownership transfer.\n     */\n    function acceptOwnership() public virtual {\n        address sender = _msgSender();\n        require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n        _transferOwnership(sender);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// contracts/libs/memory/State.sol\n\n/// State is a memory view over a formatted state payload.\ntype State is uint256;\n\nusing StateLib for State global;\n\n/// # State\n/// State structure represents the state of Origin contract at some point of time.\n/// - State is structured in a way to track the updates of the Origin Merkle Tree.\n/// - State includes root of the Origin Merkle Tree, origin domain and some additional metadata.\n/// ## Origin Merkle Tree\n/// Hash of every sent message is inserted in the Origin Merkle Tree, which changes\n/// the value of Origin Merkle Root (which is the root for the mentioned tree).\n/// - Origin has a single Merkle Tree for all messages, regardless of their destination domain.\n/// - This leads to Origin state being updated if and only if a message was sent in a block.\n/// - Origin contract is a \"source of truth\" for states: a state is considered \"valid\" in its Origin,\n/// if it matches the state of the Origin contract after the N-th (nonce) message was sent.\n///\n/// # Memory layout of State fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                    |\n/// | ---------- | ----------- | ------- | ----- | ------------------------------ |\n/// | [000..032) | root        | bytes32 | 32    | Root of the Origin Merkle Tree |\n/// | [032..036) | origin      | uint32  | 4     | Domain where Origin is located |\n/// | [036..040) | nonce       | uint32  | 4     | Amount of sent messages        |\n/// | [040..045) | blockNumber | uint40  | 5     | Block of last sent message     |\n/// | [045..050) | timestamp   | uint40  | 5     | Time of last sent message      |\n/// | [050..062) | gasData     | uint96  | 12    | Gas data for the chain         |\n///\n/// @dev State could be used to form a Snapshot to be signed by a Guard or a Notary.\nlibrary StateLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_ROOT = 0;\n    uint256 private constant OFFSET_ORIGIN = 32;\n    uint256 private constant OFFSET_NONCE = 36;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 40;\n    uint256 private constant OFFSET_TIMESTAMP = 45;\n    uint256 private constant OFFSET_GAS_DATA = 50;\n\n    // ═══════════════════════════════════════════════════ STATE ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted State payload with provided fields\n     * @param root_         New merkle root\n     * @param origin_       Domain of Origin's chain\n     * @param nonce_        Nonce of the merkle root\n     * @param blockNumber_  Block number when root was saved in Origin\n     * @param timestamp_    Block timestamp when root was saved in Origin\n     * @param gasData_      Gas data for the chain\n     * @return Formatted state\n     */\n    function formatState(\n        bytes32 root_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_,\n        GasData gasData_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(root_, origin_, nonce_, blockNumber_, timestamp_, gasData_);\n    }\n\n    /**\n     * @notice Returns a State view over the given payload.\n     * @dev Will revert if the payload is not a state.\n     */\n    function castToState(bytes memory payload) internal pure returns (State) {\n        return castToState(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a State view.\n     * @dev Will revert if the memory view is not over a state.\n     */\n    function castToState(MemView memView) internal pure returns (State) {\n        if (!isState(memView)) revert UnformattedState();\n        return State.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted State.\n    function isState(MemView memView) internal pure returns (bool) {\n        return memView.len() == STATE_LENGTH;\n    }\n\n    /// @notice Returns the hash of a State, that could be later signed by a Guard to signal\n    /// that the state is invalid.\n    function hashInvalid(State state) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(stateInvalidSalt, keccak(state))\n        return state.unwrap().keccakSalted(STATE_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(State state) internal pure returns (MemView) {\n        return MemView.wrap(State.unwrap(state));\n    }\n\n    /// @notice Compares two State structures.\n    function equals(State a, State b) internal pure returns (bool) {\n        // Length of a State payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═══════════════════════════════════════════════ STATE HASHING ═══════════════════════════════════════════════════\n\n    /// @notice Returns the hash of the State.\n    /// @dev We are using the Merkle Root of a tree with two leafs (see below) as state hash.\n    function leaf(State state) internal pure returns (bytes32) {\n        (bytes32 leftLeaf_, bytes32 rightLeaf_) = state.subLeafs();\n        // Final hash is the parent of these leafs\n        return keccak256(bytes.concat(leftLeaf_, rightLeaf_));\n    }\n\n    /// @notice Returns \"sub-leafs\" of the State. Hash of these \"sub leafs\" is going to be used\n    /// as a \"state leaf\" in the \"Snapshot Merkle Tree\".\n    /// This enables proving that leftLeaf = (root, origin) was a part of the \"Snapshot Merkle Tree\",\n    /// by combining `rightLeaf` with the remainder of the \"Snapshot Merkle Proof\".\n    function subLeafs(State state) internal pure returns (bytes32 leftLeaf_, bytes32 rightLeaf_) {\n        MemView memView = state.unwrap();\n        // Left leaf is (root, origin)\n        leftLeaf_ = memView.prefix({len_: OFFSET_NONCE}).keccak();\n        // Right leaf is (metadata), or (nonce, blockNumber, timestamp)\n        rightLeaf_ = memView.sliceFrom({index_: OFFSET_NONCE}).keccak();\n    }\n\n    /// @notice Returns the left \"sub-leaf\" of the State.\n    function leftLeaf(bytes32 root_, uint32 origin_) internal pure returns (bytes32) {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(root_, origin_));\n    }\n\n    /// @notice Returns the right \"sub-leaf\" of the State.\n    function rightLeaf(uint32 nonce_, uint40 blockNumber_, uint40 timestamp_, GasData gasData_)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(nonce_, blockNumber_, timestamp_, gasData_));\n    }\n\n    // ═══════════════════════════════════════════════ STATE SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns a historical Merkle root from the Origin contract.\n    function root(State state) internal pure returns (bytes32) {\n        return state.unwrap().index({index_: OFFSET_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns domain of chain where the Origin contract is deployed.\n    function origin(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns nonce of Origin contract at the time, when `root` was the Merkle root.\n    function nonce(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when `root` was saved in Origin.\n    function blockNumber(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when `root` was saved in Origin.\n    /// @dev This is the timestamp according to the origin chain.\n    function timestamp(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n\n    /// @notice Returns gas data for the chain.\n    function gasData(State state) internal pure returns (GasData) {\n        return GasDataLib.wrapGasData(state.unwrap().indexUint({index_: OFFSET_GAS_DATA, bytes_: GAS_DATA_LENGTH}));\n    }\n}\n\n// contracts/libs/memory/BaseMessage.sol\n\n/// BaseMessage is a memory view over the base message supported by Origin-Destination\ntype BaseMessage is uint256;\n\nusing BaseMessageLib for BaseMessage global;\n\n/// BaseMessage structure represents a base message sent via the Origin-Destination contracts.\n/// - It only contains data relevant to the base message, the rest of data is encoded in the message header.\n/// - `sender` and `recipient` for EVM chains are EVM addresses casted to bytes32, while preserving left-alignment.\n/// - `tips` and `request` parameters are specified by a message sender\n/// \u003e Origin will calculate minimum tips for given request and content length, and will reject messages with tips\n/// lower than that.\n///\n/// # Memory layout of BaseMessage fields\n///\n/// | Position   | Field     | Type    | Bytes | Description                            |\n/// | ---------- | --------- | ------- | ----- | -------------------------------------- |\n/// | [000..032) | tips      | uint256 | 32    | Encoded tips paid on origin chain      |\n/// | [032..064) | sender    | bytes32 | 32    | Sender address on origin chain         |\n/// | [064..096) | recipient | bytes32 | 32    | Recipient address on destination chain |\n/// | [096..116) | request   | uint160 | 20    | Encoded request for message execution  |\n/// | [104..AAA) | content   | bytes   | ??    | Content to be passed to recipient      |\nlibrary BaseMessageLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_TIPS = 0;\n    uint256 private constant OFFSET_SENDER = 32;\n    uint256 private constant OFFSET_RECIPIENT = 64;\n    uint256 private constant OFFSET_REQUEST = OFFSET_RECIPIENT + TIPS_LENGTH;\n    uint256 private constant OFFSET_CONTENT = OFFSET_REQUEST + REQUEST_LENGTH;\n\n    // ═══════════════════════════════════════════════ BASE MESSAGE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted BaseMessage payload with provided fields.\n     * @param tips_         Encoded tips information\n     * @param sender_       Sender address on origin chain\n     * @param recipient_    Recipient address on destination chain\n     * @param request_      Encoded request for message execution\n     * @param content_      Raw content to be passed to recipient on destination chain\n     * @return Formatted base message\n     */\n    function formatBaseMessage(Tips tips_, bytes32 sender_, bytes32 recipient_, Request request_, bytes memory content_)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return abi.encodePacked(tips_, sender_, recipient_, request_, content_);\n    }\n\n    /**\n     * @notice Returns a BaseMessage view over the given payload.\n     * @dev Will revert if the payload is not a base message.\n     */\n    function castToBaseMessage(bytes memory payload) internal pure returns (BaseMessage) {\n        return castToBaseMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a BaseMessage view.\n     * @dev Will revert if the memory view is not over a base message payload.\n     */\n    function castToBaseMessage(MemView memView) internal pure returns (BaseMessage) {\n        if (!isBaseMessage(memView)) revert UnformattedBaseMessage();\n        return BaseMessage.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted BaseMessage.\n    function isBaseMessage(MemView memView) internal pure returns (bool) {\n        // Check if sender, recipient, tips fields exist\n        return (memView.len() \u003e= OFFSET_CONTENT);\n        // Content could be empty, so we don't check that\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(BaseMessage baseMessage) internal pure returns (MemView) {\n        return MemView.wrap(BaseMessage.unwrap(baseMessage));\n    }\n\n    /// @notice Returns baseMessage's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        // We hash \"tips\" and \"everything but tips\" to make tips proofs easier to verify\n        return MerkleMath.getParent(baseMessage.tips().leaf(), baseMessage.bodyLeaf());\n    }\n\n    /// @notice Returns hash for the \"everything but tips\" part of the base message.\n    function bodyLeaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_SENDER}).keccak();\n    }\n\n    // ═══════════════════════════════════════════ BASE MESSAGE SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips paid on origin chain.\n    function tips(BaseMessage baseMessage) internal pure returns (Tips) {\n        return TipsLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_TIPS, bytes_: TIPS_LENGTH})));\n    }\n\n    /// @notice Returns sender address on origin chain.\n    function sender(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_SENDER, bytes_: 32});\n    }\n\n    /// @notice Returns recipient address on destination chain.\n    function recipient(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_RECIPIENT, bytes_: 32});\n    }\n\n    /// @notice Returns an encoded request for message execution on destination chain.\n    function request(BaseMessage baseMessage) internal pure returns (Request) {\n        return RequestLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_REQUEST, bytes_: REQUEST_LENGTH})));\n    }\n\n    /// @notice Returns an untyped memory view over the content to be passed to recipient.\n    function content(BaseMessage baseMessage) internal pure returns (MemView) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_CONTENT});\n    }\n}\n\n// contracts/base/MessagingBase.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for all messaging contracts.\n * - Provides context on the local chain's domain.\n * - Provides ownership functionality.\n * - Will be providing pausing functionality when it is implemented.\n */\nabstract contract MessagingBase is MultiCallable, Versioned, Ownable2StepUpgradeable {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @notice Domain of the local chain, set once upon contract creation\n    uint32 public immutable localDomain;\n    // @notice Domain of the Synapse chain, set once upon contract creation\n    uint32 public immutable synapseDomain;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev gap for upgrade safety\n    uint256[50] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    constructor(string memory version_, uint32 synapseDomain_) Versioned(version_) {\n        localDomain = ChainContext.chainId();\n        synapseDomain = synapseDomain_;\n    }\n\n    // TODO: Implement pausing\n\n    /**\n     * @dev Should be impossible to renounce ownership;\n     * we override OpenZeppelin OwnableUpgradeable's\n     * implementation of renounceOwnership to make it a no-op\n     */\n    function renounceOwnership() public override onlyOwner {} //solhint-disable-line no-empty-blocks\n}\n\n// contracts/libs/memory/Message.sol\n\n/// Message is a memory over over a formatted message payload.\ntype Message is uint256;\n\nusing MessageLib for Message global;\n\n/// Library for formatting the various messages supported by Origin and Destination.\n///\n/// # Message memory layout\n///\n/// | Position   | Field  | Type    | Bytes | Description                                             |\n/// | ---------- | ------ | ------- | ----- | ------------------------------------------------------- |\n/// | [000..017) | header | uint136 | 17    | Encoded general routing information for the message     |\n/// | [017..AAA) | body   | bytes   | ??    | Formatted payload (according to flag) with message body |\nlibrary MessageLib {\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MemViewLib for bytes;\n    using HeaderLib for MemView;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_HEADER = 0;\n    uint256 private constant OFFSET_BODY = OFFSET_HEADER + HEADER_LENGTH;\n\n    // ══════════════════════════════════════════════════ MESSAGE ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns formatted message with provided fields.\n     * @param header_   Encoded general routing information for the message\n     * @param body_     Formatted payload (according to flag) with message body\n     * @return Formatted message\n     */\n    function formatMessage(Header header_, bytes memory body_) internal pure returns (bytes memory) {\n        return abi.encodePacked(header_, body_);\n    }\n\n    /**\n     * @notice Returns a Message view over for the given payload.\n     * @dev Will revert if the payload is not a message payload.\n     */\n    function castToMessage(bytes memory payload) internal pure returns (Message) {\n        return castToMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Message view.\n     * @dev Will revert if the memory view is not over a message payload.\n     */\n    function castToMessage(MemView memView) internal pure returns (Message) {\n        if (!isMessage(memView)) revert UnformattedMessage();\n        return Message.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Message.\n     */\n    function isMessage(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Check if headers exist in the payload\n        if (length \u003c OFFSET_BODY) return false;\n        // Check that Header is valid\n        uint256 paddedHeader = _header(memView);\n        if (!HeaderLib.isHeader(paddedHeader)) return false;\n        // Check that body is formatted according to the flag\n        // Only Base/Manager message flags exist\n        if (HeaderLib.wrapPadded(paddedHeader).flag() == MessageFlag.Base) {\n            // Check if body is a formatted base message\n            return _body(memView).isBaseMessage();\n        } else {\n            // Check if body is a formatted calldata for AgentManager call\n            return _body(memView).isCallData();\n        }\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Message message) internal pure returns (MemView) {\n        return MemView.wrap(Message.unwrap(message));\n    }\n\n    /// @notice Returns message's hash: a leaf to be inserted in the Merkle tree.\n    function leaf(Message message) internal pure returns (bytes32) {\n        // We hash header and body separately to make message proofs easier to verify\n        Header header_ = message.header();\n        // Only Base/Manager message flags exist\n        if (header_.flag() == MessageFlag.Base) {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToBaseMessage().leaf());\n        } else {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToCallData().leaf());\n        }\n    }\n\n    // ══════════════════════════════════════════════ MESSAGE SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns message's encoded header field.\n    function header(Message message) internal pure returns (Header) {\n        return HeaderLib.wrapPadded((message.unwrap().indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH})));\n    }\n\n    /// @notice Returns message's body field as an untyped memory view.\n    function body(Message message) internal pure returns (MemView) {\n        MemView memView = message.unwrap();\n        return _body(memView);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns message's padded header without checking that it is a valid header.\n    function _header(MemView memView) private pure returns (uint256) {\n        return memView.indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH});\n    }\n\n    /// @dev Returns an untyped memory view over the body field without checking\n    /// if the whole payload or the body are properly formatted.\n    function _body(MemView memView) private pure returns (MemView) {\n        return memView.sliceFrom({index_: OFFSET_BODY});\n    }\n}\n\n// contracts/base/AgentSecured.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for messaging contracts that are secured by the agent manager.\n * `AgentSecured` relies on `AgentManager` to provide the following functionality:\n * - Keep track of agents and their statuses.\n * - Pass agent-signed statements that were verified by the agent manager.\n * - These statements are considered valid indefinitely, unless the agent is disputed.\n * - Disputes are opened and resolved by the agent manager.\n * \u003e `AgentSecured` implementation should never use statements signed by agents that are disputed.\n */\nabstract contract AgentSecured is MessagingBase, IAgentSecured {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    address public immutable agentManager;\n\n    /// @inheritdoc IAgentSecured\n    address public immutable inbox;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    // (agent index =\u003e their dispute status: flag, openedAt, resolvedAt)\n    mapping(uint32 =\u003e DisputeStatus) internal _disputes;\n\n    /// @dev gap for upgrade safety\n    uint256[49] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    modifier onlyAgentManager() {\n        if (msg.sender != agentManager) revert CallerNotAgentManager();\n        _;\n    }\n\n    modifier onlyInbox() {\n        if (msg.sender != inbox) revert CallerNotInbox();\n        _;\n    }\n\n    constructor(string memory version_, uint32 synapseDomain_, address agentManager_, address inbox_)\n        MessagingBase(version_, synapseDomain_)\n    {\n        agentManager = agentManager_;\n        inbox = inbox_;\n    }\n\n    // ════════════════════════════════════════════ ONLY AGENT MANAGER ═════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external onlyAgentManager {\n        uint40 openedAt = ChainContext.blockTimestamp();\n        DisputeStatus memory status = DisputeStatus({flag: DisputeFlag.Pending, openedAt: openedAt, resolvedAt: 0});\n        _disputes[guardIndex] = status;\n        _disputes[notaryIndex] = status;\n    }\n\n    /// @inheritdoc IAgentSecured\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external onlyAgentManager {\n        // Update the dispute status of the slashed agent first.\n        uint40 resolvedAt = ChainContext.blockTimestamp();\n        _disputes[slashedIndex].flag = DisputeFlag.Slashed;\n        _disputes[slashedIndex].resolvedAt = resolvedAt;\n        // Mark the rival agent as not disputed, if there was an ongoing dispute.\n        if (rivalIndex != 0) {\n            _disputes[rivalIndex].flag = DisputeFlag.None;\n            _disputes[rivalIndex].resolvedAt = resolvedAt;\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function agentStatus(address agent) external view returns (AgentStatus memory) {\n        return _agentStatus(agent);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status) {\n        return _getAgent(index);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory) {\n        return _disputes[agentIndex];\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns status of the given agent: (flag, domain, index).\n    function _agentStatus(address agent) internal view returns (AgentStatus memory) {\n        return IAgentManager(agentManager).agentStatus(agent);\n    }\n\n    /// @dev Returns agent and their status for a given agent index. Returns zero values for non existing indexes.\n    function _getAgent(uint256 index) internal view returns (address agent, AgentStatus memory status) {\n        return IAgentManager(agentManager).getAgent(index);\n    }\n\n    /// @dev Checks if a Dispute exists for the given Notary. This function returns true, if\n    /// Notary is in ongoing Dispute, or if Dispute was resolved not in Notary's favor.\n    /// In both cases we can't trust Notary's data.\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeExists(uint32 notaryIndex) internal view returns (bool) {\n        return _disputes[notaryIndex].flag != DisputeFlag.None;\n    }\n\n    /// @dev Checks if a Notary recently won a Dispute and is still in the \"post-dispute\" timeout period.\n    /// In this period we still can't trust Notary's data, though we can optimistically assume that\n    /// that the data will be correct after the timeout (assuming no new Disputes are opened).\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeTimeout(uint32 notaryIndex) internal view returns (bool) {\n        DisputeStatus memory status = _disputes[notaryIndex];\n        // Exit early if Notary is in ongoing Dispute / slashed.\n        if (status.flag != DisputeFlag.None) return false;\n        // Check if Notary has been in any Dispute at all.\n        if (status.openedAt == 0) return false;\n        // Otherwise check if the Dispute timeout is still active.\n        return block.timestamp \u003c status.resolvedAt + DISPUTE_TIMEOUT_NOTARY;\n    }\n}\n\n// contracts/hubs/StateHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StateHub` is a parent contract for `Origin`. It is responsible for the following:\n/// - Keeping track of the historical Origin Merkle Tree containing all the message hashes.\n/// - Keeping track of the historical Origin States, as well as verifying their validity.\nabstract contract StateHub is AgentSecured, StateHubEvents, IStateHub {\n    using SafeCast for uint256;\n    using StateLib for bytes;\n\n    struct OriginState {\n        uint40 blockNumber;\n        uint40 timestamp;\n        GasData gasData;\n    }\n    // Bits left for tight packing: 80\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Historical Merkle Tree\n    /// Note: Takes two storage slots\n    HistoricalTree private _tree;\n\n    /// @dev All historical contract States\n    OriginState[] private _originStates;\n\n    /// @dev gap for upgrade safety\n    uint256[47] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IStateHub\n    function isValidState(bytes memory statePayload) external view returns (bool isValid) {\n        // This will revert if payload is not a formatted state\n        State state = statePayload.castToState();\n        return _isValidState(state);\n    }\n\n    /// @inheritdoc IStateHub\n    function statesAmount() external view returns (uint256) {\n        return _originStates.length;\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestLatestState() external view returns (bytes memory stateData) {\n        // This never underflows, assuming the contract was initialized\n        return suggestState(_nextNonce() - 1);\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestState(uint32 nonce) public view returns (bytes memory stateData) {\n        // This will revert if nonce is out of range\n        bytes32 root = _tree.root(nonce);\n        return _formatOriginState(_originStates[nonce], root, localDomain, nonce);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Initializes the saved states list by inserting a state for an empty Merkle Tree.\n    function _initializeStates() internal {\n        // This should only be called once, when the contract is initialized\n        // This will revert if _tree.roots is non-empty\n        bytes32 savedRoot = _tree.initializeRoots();\n        // Save root for empty merkle _tree with block number and timestamp of initialization\n        _saveState(savedRoot, _toOriginState());\n    }\n\n    /// @dev Inserts leaf into the Merkle Tree and saves the updated origin State.\n    function _insertAndSave(bytes32 leaf) internal {\n        bytes32 newRoot = _tree.insert(leaf);\n        _saveState(newRoot, _toOriginState());\n    }\n\n    /// @dev Saves an updated state of the Origin contract\n    function _saveState(bytes32 root, OriginState memory state) internal {\n        uint32 nonce = _nextNonce();\n        _originStates.push(state);\n        // Emit event with raw state data\n        emit StateSaved(_formatOriginState(state, root, localDomain, nonce));\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns nonce of the next sent message: the amount of saved States so far.\n    /// This always equals to \"total amount of sent messages\" plus 1.\n    function _nextNonce() internal view returns (uint32) {\n        // TODO: consider using more than 32 bits for origin nonces\n        return _originStates.length.toUint32();\n    }\n\n    /// @dev Checks if a state is valid, i.e. if it matches the historical one.\n    /// Reverts, if state refers to another Origin contract.\n    function _isValidState(State state) internal view returns (bool) {\n        // Check if state refers to this contract\n        if (state.origin() != localDomain) revert IncorrectOriginDomain();\n        // Check if nonce exists\n        uint32 nonce = state.nonce();\n        if (nonce \u003e= _originStates.length) return false;\n        // Check if state root matches the historical one\n        if (state.root() != _tree.root(nonce)) return false;\n        // Check if state metadata matches the historical one\n        return _areEqual(state, _originStates[nonce]);\n    }\n\n    // ═════════════════════════════════════════════ STRUCT FORMATTING ═════════════════════════════════════════════════\n\n    /// @dev Returns a formatted payload for a stored OriginState.\n    function _formatOriginState(OriginState memory originState, bytes32 root, uint32 origin, uint32 nonce)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return StateLib.formatState({\n            root_: root,\n            origin_: origin,\n            nonce_: nonce,\n            blockNumber_: originState.blockNumber,\n            timestamp_: originState.timestamp,\n            gasData_: originState.gasData\n        });\n    }\n\n    /// @dev Child contract should implement the logic for getting the current gas data from the gas oracle\n    /// to be saved as part of the Origin State.\n    // solhint-disable-next-line ordering\n    function _fetchGasData() internal view virtual returns (GasData);\n\n    /// @dev Returns a OriginState struct to save in the contract.\n    function _toOriginState() internal view returns (OriginState memory originState) {\n        originState.blockNumber = ChainContext.blockNumber();\n        originState.timestamp = ChainContext.blockTimestamp();\n        originState.gasData = _fetchGasData();\n    }\n\n    /// @dev Checks that a state and its Origin representation are equal.\n    function _areEqual(State state, OriginState memory originState) internal pure returns (bool) {\n        return state.blockNumber() == originState.blockNumber \u0026\u0026 state.timestamp() == originState.timestamp;\n    }\n}\n\n// contracts/Origin.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Origin` contract is used for sending messages to remote chains. It is done\n/// by inserting the message hashes into the Origin Merkle, which makes it possible to\n/// prove that message was sent using the Merkle proof against the Origin Merkle Root. This essentially\n/// compresses the list of messages into a single 32-byte value that needs to be stored on the destination chain.\n/// `Origin` is responsible for the following:\n/// - Formatting the sent message payloads, and inserting their hashes into the Origin Merkle Tree.\n/// - Keeping track of its own historical states (see parent contract `StateHub`).\n/// - Enforcing minimum tip values for sent base messages based on the provided execution requests.\n/// - Distributing the collected tips upon request from a local `AgentManager` contract.\ncontract Origin is StateHub, OriginEvents, InterfaceOrigin {\n    using MemViewLib for bytes;\n    using MessageLib for bytes;\n    using TipsLib for bytes;\n    using TypeCasts for address;\n\n    address public immutable gasOracle;\n\n    modifier onlyRemoteDestination(uint32 destination) {\n        if (destination == localDomain) revert IncorrectDestinationDomain();\n        _;\n    }\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_, address gasOracle_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {\n        gasOracle = gasOracle_;\n    }\n\n    /// @notice Initializes Origin contract:\n    /// - msg.sender is set as contract owner\n    /// - State of \"empty merkle tree\" is saved\n    function initialize() external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize \"states\": state of an \"empty merkle tree\" is saved\n        _initializeStates();\n    }\n\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable onlyRemoteDestination(destination) returns (uint32 messageNonce, bytes32 messageHash) {\n        // Check that content is not too large\n        if (content.length \u003e MAX_CONTENT_BYTES) revert ContentLengthTooBig();\n        // This will revert if msg.value is lower than value of minimum tips\n        Tips tips = _getMinimumTips(destination, paddedRequest, content.length).matchValue(msg.value);\n        Request request = RequestLib.wrapPadded(paddedRequest);\n        // Format the BaseMessage body\n        bytes memory body = BaseMessageLib.formatBaseMessage({\n            sender_: msg.sender.addressToBytes32(),\n            recipient_: recipient,\n            tips_: tips,\n            request_: request,\n            content_: content\n        });\n        // Send the message\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Base, body);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        onlyAgentManager\n        onlyRemoteDestination(destination)\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // AgentManager (checked via modifier) is responsible for constructing the calldata payload correctly.\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Manager, payload);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function withdrawTips(address recipient, uint256 amount) external onlyAgentManager {\n        if (address(this).balance \u003c amount) revert InsufficientEthBalance();\n        (bool success,) = recipient.call{value: amount}(\"\");\n        if (!success) revert EthTransferFailed();\n        emit TipWithdrawalCompleted(recipient, amount);\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue)\n    {\n        return _getMinimumTips(destination, paddedRequest, contentLength).value();\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Sends the given message to the specified destination. Message hash is inserted\n    /// into the Origin Merkle Tree, which will enable message execution on destination chain.\n    function _sendMessage(uint32 destination, uint32 optimisticPeriod, MessageFlag flag, bytes memory body)\n        internal\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // Format the message header\n        messageNonce = _nextNonce();\n        Header header = flag.encodeHeader({\n            origin_: localDomain,\n            nonce_: messageNonce,\n            destination_: destination,\n            optimisticPeriod_: optimisticPeriod\n        });\n        // Format the full message payload\n        bytes memory msgPayload = MessageLib.formatMessage(header, body);\n        // Insert new leaf into the Origin Merkle Tree and save the updated state\n        messageHash = msgPayload.castToMessage().leaf();\n        _insertAndSave(messageHash);\n        // Emit event with message information\n        emit Sent(messageHash, messageNonce, destination, msgPayload);\n        // Update the gas oracle data. We do this after the provided tips are checked so that\n        // the provided message is sent in the event that the gas oracle data is updated to a higher value.\n        InterfaceGasOracle(gasOracle).updateGasData(destination);\n        // TODO: consider doing this before the message is sent, while adjusting GasOracle.getMinimumTips() to\n        // use the pending gas oracle data.\n    }\n\n    /// @dev Returns the minimum tips for sending a message to the given destination with the given request and content.\n    function _getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        internal\n        view\n        returns (Tips)\n    {\n        return\n            TipsLib.wrapPadded(InterfaceGasOracle(gasOracle).getMinimumTips(destination, paddedRequest, contentLength));\n    }\n\n    /// @dev Gets the current gas data from the gas oracle to be saved as part of the Origin State.\n    function _fetchGasData() internal view override returns (GasData) {\n        return GasDataLib.wrapGasData(InterfaceGasOracle(gasOracle).getGasData());\n    }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"","srcMapRuntime":"","abiDefinition":[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"Provides information about the current execution context, including the sender of the transaction and its data. While these are generally available via msg.sender and msg.data, they should not be accessed in such a direct manner, since when dealing with meta-transactions the account sending and paying for execution may not be the actual sender (as far as an application is concerned). This contract is only required for intermediate, library-like contracts.","kind":"dev","methods":{},"stateVariables":{"__gap":{"details":"This empty reserved space is put in place to allow future versions to add new variables without shifting down storage in the inheritance chain. See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps"}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"}],\"devdoc\":{\"details\":\"Provides information about the current execution context, including the sender of the transaction and its data. While these are generally available via msg.sender and msg.data, they should not be accessed in such a direct manner, since when dealing with meta-transactions the account sending and paying for execution may not be the actual sender (as far as an application is concerned). This contract is only required for intermediate, library-like contracts.\",\"kind\":\"dev\",\"methods\":{},\"stateVariables\":{\"__gap\":{\"details\":\"This empty reserved space is put in place to allow future versions to add new variables without shifting down storage in the inheritance chain. See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Origin.sol\":\"ContextUpgradeable\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Origin.sol\":{\"keccak256\":\"0x96775924f147f3d1f8df8cdf56731fe52a15af8d8e12e608efb8158c112b18cd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e642a27f5fab3c62b4c02e9754e9e42b1cf2e5381dbea9d3d106d23b7772ebe6\",\"dweb:/ipfs/QmUwn7ZyBvPkjnMuK8ZMSexBUdNQnVtxwyoAyT4DXLQjra\"]}},\"version\":1}"},"hashes":{}},"solidity/Origin.sol:GasDataLib":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212207e9fab9c8210247382c7d3599b717474ebc1545164235e50889e99c5cab40f7864736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212207e9fab9c8210247382c7d3599b717474ebc1545164235e50889e99c5cab40f7864736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/OriginEvents.sol\n\n/// @notice A collection of events emitted by the Origin contract\nabstract contract OriginEvents {\n    /**\n     * @notice Emitted when a new message is sent.\n     * @param messageHash   Hash of message; the leaf inserted to the Merkle tree for the message\n     * @param nonce         Nonce of sent message (starts from 1)\n     * @param destination   Destination domain\n     * @param message       Raw bytes of message\n     */\n    event Sent(bytes32 indexed messageHash, uint32 indexed nonce, uint32 indexed destination, bytes message);\n\n    /**\n     * @notice Emitted when a tip withdrawal is completed.\n     * @param actor     Actor address\n     * @param tip       Tip value, denominated in local domain's wei\n     */\n    event TipWithdrawalCompleted(address actor, uint256 tip);\n}\n\n// contracts/events/StateHubEvents.sol\n\n/// @notice A collection of events emitted by the StateHub contract\nabstract contract StateHubEvents {\n    /**\n     * @notice Emitted when a new Origin State is saved after a message was sent.\n     * @param state     Raw payload with state data\n     */\n    event StateSaved(bytes state);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n    /**\n     * @notice Check that a given state is valid: matches the historical state of Origin contract.\n     * Note: any Agent including an invalid state in their snapshot will be slashed\n     * upon providing the snapshot and agent signature for it to Origin contract.\n     * @dev Will revert if any of these is true:\n     *  - State payload is not properly formatted.\n     * @param statePayload      Raw payload with state data\n     * @return isValid          Whether the provided state is valid\n     */\n    function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns the amount of saved states so far.\n     * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n     */\n    function statesAmount() external view returns (uint256);\n\n    /**\n     * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @return statePayload     Raw payload with the latest state data\n     */\n    function suggestLatestState() external view returns (bytes memory statePayload);\n\n    /**\n     * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @param nonce             Historical nonce to form a state\n     * @return statePayload     Raw payload with historical state data\n     */\n    function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/InterfaceGasOracle.sol\n\ninterface InterfaceGasOracle {\n    /**\n     * @notice Fetches the latest gas data for the chain from `Destination` contract,\n     * and uses it to update the oracle values for the requested chain.\n     * @param domain    Domain to update the gas data for\n     */\n    function updateGasData(uint32 domain) external;\n\n    /**\n     * @notice Returns the gas data for the local chain.\n     */\n    function getGasData() external view returns (uint256 paddedGasData);\n\n    /**\n     * @notice Returns the gas data for the given domain, in the decoded format.\n     * @param domain        Domain of chain to get gas data for\n     * @return gasPrice     Gas price for the chain (in Wei per gas unit)\n     * @return dataPrice    Calldata price (in Wei per byte of content)\n     * @return execBuffer   Tx fee safety buffer for message execution (in Wei)\n     * @return amortAttCost Amortized cost for attestation submission (in Wei)\n     * @return etherPrice   Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n     * @return markup       Markup for the message execution (in BWAD)\n     */\n    function getDecodedGasData(uint32 domain)\n        external\n        view\n        returns (\n            uint256 gasPrice,\n            uint256 dataPrice,\n            uint256 execBuffer,\n            uint256 amortAttCost,\n            uint256 etherPrice,\n            uint256 markup\n        );\n\n    /**\n     * @notice Returns the minimum tips for sending a message to a given destination.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return paddedTips       Padded encoded minimum tips information\n     */\n    function getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 paddedTips);\n}\n\n// contracts/interfaces/InterfaceOrigin.sol\n\ninterface InterfaceOrigin {\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /**\n     * @notice Send a message to the recipient located on destination domain.\n     * @dev Recipient has to conform to IMessageRecipient interface, otherwise message won't be delivered.\n     * Will revert if any of these is true:\n     * - `destination` is equal to contract's local domain\n     * - `content` length is greater than `MAX_CONTENT_BYTES`\n     * - `msg.value` is lower than value of minimum tips for the given message\n     * @param destination           Domain of destination chain\n     * @param recipient             Address of recipient on destination chain as bytes32\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param paddedRequest         Padded encoded message execution request on destination chain\n     * @param content               Raw bytes content of message\n     * @return messageNonce         Nonce of the sent message\n     * @return messageHash          Hash of the sent message\n     */\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable returns (uint32 messageNonce, bytes32 messageHash);\n\n    /**\n     * @notice Send a manager message to the destination domain.\n     * @dev This could only be called by AgentManager, which takes care of encoding the calldata payload.\n     * Note: (msgOrigin, proofMaturity) security args will be added to payload on the destination chain\n     * so that the AgentManager could verify where the Manager Message came from and how mature is the proof.\n     * Note: function is not payable, as no tips are required for sending a manager message.\n     * Will revert if `destination` is equal to contract's local domain.\n     * @param destination           Domain of destination chain\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param payload               Payload for calling AgentManager on destination chain (with extra security args)\n     */\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        returns (uint32 messageNonce, bytes32 messageHash);\n\n    // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Withdraws locked base message tips to the recipient.\n     * @dev Could only be called by a local AgentManager.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function withdrawTips(address recipient, uint256 amount) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the minimum tips value for sending a message to a given destination.\n     * @dev Using at least `tipsValue` as `msg.value` for `sendBaseMessage()`\n     * will guarantee that the message will be accepted.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return tipsValue        Minimum tips value for a message to be accepted\n     */\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue);\n}\n\n// contracts/libs/Constants.sol\n\n// Here we define common constants to enable their easier reusing later.\n\n// ══════════════════════════════════ MERKLE ═══════════════════════════════════\n/// @dev Height of the Agent Merkle Tree\nuint256 constant AGENT_TREE_HEIGHT = 32;\n/// @dev Height of the Origin Merkle Tree\nuint256 constant ORIGIN_TREE_HEIGHT = 32;\n/// @dev Height of the Snapshot Merkle Tree. Allows up to 64 leafs, e.g. up to 32 states\nuint256 constant SNAPSHOT_TREE_HEIGHT = 6;\n// ══════════════════════════════════ STRUCTS ══════════════════════════════════\n/// @dev See Attestation.sol: (bytes32,bytes32,uint32,uint40,uint40): 32+32+4+5+5\nuint256 constant ATTESTATION_LENGTH = 78;\n/// @dev See GasData.sol: (uint16,uint16,uint16,uint16,uint16,uint16): 2+2+2+2+2+2\nuint256 constant GAS_DATA_LENGTH = 12;\n/// @dev See Receipt.sol: (uint32,uint32,bytes32,bytes32,uint8,address,address,address): 4+4+32+32+1+20+20+20\nuint256 constant RECEIPT_LENGTH = 133;\n/// @dev See State.sol: (bytes32,uint32,uint32,uint40,uint40,GasData): 32+4+4+5+5+len(GasData)\nuint256 constant STATE_LENGTH = 50 + GAS_DATA_LENGTH;\n/// @dev Maximum amount of states in a single snapshot. Each state produces two leafs in the tree\nuint256 constant SNAPSHOT_MAX_STATES = 1 \u003c\u003c (SNAPSHOT_TREE_HEIGHT - 1);\n// ══════════════════════════════════ MESSAGE ══════════════════════════════════\n/// @dev See Header.sol: (uint8,uint32,uint32,uint32,uint32): 1+4+4+4+4\nuint256 constant HEADER_LENGTH = 17;\n/// @dev See Request.sol: (uint96,uint64,uint32): 12+8+4\nuint256 constant REQUEST_LENGTH = 24;\n/// @dev See Tips.sol: (uint64,uint64,uint64,uint64): 8+8+8+8\nuint256 constant TIPS_LENGTH = 32;\n/// @dev The amount of discarded last bits when encoding tip values\nuint256 constant TIPS_GRANULARITY = 32;\n/// @dev Tip values could be only the multiples of TIPS_MULTIPLIER\nuint256 constant TIPS_MULTIPLIER = 1 \u003c\u003c TIPS_GRANULARITY;\n// ══════════════════════════════ STATEMENT SALTS ══════════════════════════════\n/// @dev Salts for signing various statements\nbytes32 constant ATTESTATION_VALID_SALT = keccak256(\"ATTESTATION_VALID_SALT\");\nbytes32 constant ATTESTATION_INVALID_SALT = keccak256(\"ATTESTATION_INVALID_SALT\");\nbytes32 constant RECEIPT_VALID_SALT = keccak256(\"RECEIPT_VALID_SALT\");\nbytes32 constant RECEIPT_INVALID_SALT = keccak256(\"RECEIPT_INVALID_SALT\");\nbytes32 constant SNAPSHOT_VALID_SALT = keccak256(\"SNAPSHOT_VALID_SALT\");\nbytes32 constant STATE_INVALID_SALT = keccak256(\"STATE_INVALID_SALT\");\n// ═════════════════════════════════ PROTOCOL ══════════════════════════════════\n/// @dev Optimistic period for new agent roots in LightManager\nuint32 constant AGENT_ROOT_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Timeout between the agent root could be proposed and resolved in LightManager\nuint32 constant AGENT_ROOT_PROPOSAL_TIMEOUT = 12 hours;\nuint32 constant BONDING_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Amount of time that the Notary will not be considered active after they won a dispute\nuint32 constant DISPUTE_TIMEOUT_NOTARY = 12 hours;\n/// @dev Amount of time without fresh data from Notaries before contract owner can resolve stuck disputes manually\nuint256 constant FRESH_DATA_TIMEOUT = 4 hours;\n/// @dev Maximum bytes per message = 2 KiB (somewhat arbitrarily set to begin)\nuint256 constant MAX_CONTENT_BYTES = 2 * 2 ** 10;\n/// @dev Maximum value for the summit tip that could be set in GasOracle\nuint256 constant MAX_SUMMIT_TIP = 0.01 ether;\n\n// contracts/libs/Errors.sol\n\n// ══════════════════════════════ INVALID CALLER ═══════════════════════════════\n\nerror CallerNotAgentManager();\nerror CallerNotDestination();\nerror CallerNotInbox();\nerror CallerNotSummit();\n\n// ══════════════════════════════ INCORRECT DATA ═══════════════════════════════\n\nerror IncorrectAttestation();\nerror IncorrectAgentDomain();\nerror IncorrectAgentIndex();\nerror IncorrectAgentProof();\nerror IncorrectAgentRoot();\nerror IncorrectDataHash();\nerror IncorrectDestinationDomain();\nerror IncorrectOriginDomain();\nerror IncorrectSnapshotProof();\nerror IncorrectSnapshotRoot();\nerror IncorrectState();\nerror IncorrectStatesAmount();\nerror IncorrectTipsProof();\nerror IncorrectVersionLength();\n\nerror IncorrectNonce();\nerror IncorrectSender();\nerror IncorrectRecipient();\n\nerror FlagOutOfRange();\nerror IndexOutOfRange();\nerror NonceOutOfRange();\n\nerror OutdatedNonce();\n\nerror UnformattedAttestation();\nerror UnformattedAttestationReport();\nerror UnformattedBaseMessage();\nerror UnformattedCallData();\nerror UnformattedCallDataPrefix();\nerror UnformattedMessage();\nerror UnformattedReceipt();\nerror UnformattedReceiptReport();\nerror UnformattedSignature();\nerror UnformattedSnapshot();\nerror UnformattedState();\nerror UnformattedStateReport();\n\n// ═══════════════════════════════ MERKLE TREES ════════════════════════════════\n\nerror LeafNotProven();\nerror MerkleTreeFull();\nerror NotEnoughLeafs();\nerror TreeHeightTooLow();\n\n// ═════════════════════════════ OPTIMISTIC PERIOD ═════════════════════════════\n\nerror BaseClientOptimisticPeriod();\nerror MessageOptimisticPeriod();\nerror SlashAgentOptimisticPeriod();\nerror WithdrawTipsOptimisticPeriod();\nerror ZeroProofMaturity();\n\n// ═══════════════════════════════ AGENT MANAGER ═══════════════════════════════\n\nerror AgentNotGuard();\nerror AgentNotNotary();\n\nerror AgentCantBeAdded();\nerror AgentNotActive();\nerror AgentNotActiveNorUnstaking();\nerror AgentNotFraudulent();\nerror AgentNotUnstaking();\nerror AgentUnknown();\n\nerror AgentRootNotProposed();\nerror AgentRootTimeoutNotOver();\n\nerror NotStuck();\n\nerror DisputeAlreadyResolved();\nerror DisputeNotOpened();\nerror DisputeTimeoutNotOver();\nerror GuardInDispute();\nerror NotaryInDispute();\n\nerror MustBeSynapseDomain();\nerror SynapseDomainForbidden();\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\nerror AlreadyExecuted();\nerror AlreadyFailed();\nerror DuplicatedSnapshotRoot();\nerror IncorrectMagicValue();\nerror GasLimitTooLow();\nerror GasSuppliedTooLow();\n\n// ══════════════════════════════════ ORIGIN ═══════════════════════════════════\n\nerror ContentLengthTooBig();\nerror EthTransferFailed();\nerror InsufficientEthBalance();\n\n// ════════════════════════════════ GAS ORACLE ═════════════════════════════════\n\nerror LocalGasDataNotSet();\nerror RemoteGasDataNotSet();\n\n// ═══════════════════════════════════ TIPS ════════════════════════════════════\n\nerror SummitTipTooHigh();\nerror TipsClaimMoreThanEarned();\nerror TipsClaimZero();\nerror TipsOverflow();\nerror TipsValueTooLow();\n\n// ════════════════════════════════ MEMORY VIEW ════════════════════════════════\n\nerror IndexedTooMuch();\nerror ViewOverrun();\nerror OccupiedMemory();\nerror UnallocatedMemory();\nerror PrecompileOutOfGas();\n\n// ═════════════════════════════════ MULTICALL ═════════════════════════════════\n\nerror MulticallFailed();\n\n// contracts/libs/TypeCasts.sol\n\nlibrary TypeCasts {\n    // alignment preserving cast\n    function addressToBytes32(address addr) internal pure returns (bytes32) {\n        return bytes32(uint256(uint160(addr)));\n    }\n\n    // alignment preserving cast\n    function bytes32ToAddress(bytes32 buf) internal pure returns (address) {\n        return address(uint160(uint256(buf)));\n    }\n}\n\n// contracts/libs/stack/Number.sol\n\n/// Number is a compact representation of uint256, that is fit into 16 bits\n/// with the maximum relative error under 0.4%.\ntype Number is uint16;\n\nusing NumberLib for Number global;\n\n/// # Number\n/// Library for compact representation of uint256 numbers.\n/// - Number is stored using mantissa and exponent, each occupying 8 bits.\n/// - Numbers under 2**8 are stored as `mantissa` with `exponent = 0xFF`.\n/// - Numbers at least 2**8 are approximated as `(256 + mantissa) \u003c\u003c exponent`\n/// \u003e - `0 \u003c= mantissa \u003c 256`\n/// \u003e - `0 \u003c= exponent \u003c= 247` (`256 * 2**248` doesn't fit into uint256)\n/// # Number stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type  | Bytes |\n/// | ---------- | -------- | ----- | ----- |\n/// | (002..001] | mantissa | uint8 | 1     |\n/// | (001..000] | exponent | uint8 | 1     |\n\nlibrary NumberLib {\n    /// @dev Amount of bits to shift to mantissa field\n    uint16 private constant SHIFT_MANTISSA = 8;\n\n    /// @notice For bwad math (binary wad) we use 2**64 as \"wad\" unit.\n    /// @dev We are using not using 10**18 as wad, because it is not stored precisely in NumberLib.\n    uint256 internal constant BWAD_SHIFT = 64;\n    uint256 internal constant BWAD = 1 \u003c\u003c BWAD_SHIFT;\n    /// @notice ~0.1% in bwad units.\n    uint256 internal constant PER_MILLE_SHIFT = BWAD_SHIFT - 10;\n    uint256 internal constant PER_MILLE = 1 \u003c\u003c PER_MILLE_SHIFT;\n\n    /// @notice Compresses uint256 number into 16 bits.\n    function compress(uint256 value) internal pure returns (Number) {\n        // Find `msb` such as `2**msb \u003c= value \u003c 2**(msb + 1)`\n        uint256 msb = mostSignificantBit(value);\n        // We want to preserve 9 bits of precision.\n        // The highest bit is always 1, so we can skip it.\n        // The remaining 8 highest bits are stored as mantissa.\n        if (msb \u003c 8) {\n            // Value is less than 2**8, so we can use value as mantissa with \"-1\" exponent.\n            return _encode(uint8(value), 0xFF);\n        } else {\n            // We use `msb - 8` as exponent otherwise. Note that `exponent \u003e= 0`.\n            unchecked {\n                uint256 exponent = msb - 8;\n                // Shifting right by `msb-8` bits will shift the \"remaining 8 highest bits\" into the 8 lowest bits.\n                // uint8() will truncate the highest bit.\n                return _encode(uint8(value \u003e\u003e exponent), uint8(exponent));\n            }\n        }\n    }\n\n    /// @notice Decompresses 16 bits number into uint256.\n    /// @dev The outcome is an approximation of the original number: `(value - value / 256) \u003c number \u003c= value`.\n    function decompress(Number number) internal pure returns (uint256 value) {\n        // Isolate 8 highest bits as the mantissa.\n        uint256 mantissa = Number.unwrap(number) \u003e\u003e SHIFT_MANTISSA;\n        // This will truncate the highest bits, leaving only the exponent.\n        uint256 exponent = uint8(Number.unwrap(number));\n        if (exponent == 0xFF) {\n            return mantissa;\n        } else {\n            unchecked {\n                return (256 + mantissa) \u003c\u003c (exponent);\n            }\n        }\n    }\n\n    /// @dev Returns the most significant bit of `x`\n    /// https://solidity-by-example.org/bitwise/\n    function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\n        // To find `msb` we determine it bit by bit, starting from the highest one.\n        // `0 \u003c= msb \u003c= 255`, so we start from the highest bit, 1\u003c\u003c7 == 128.\n        // If `x` is at least 2**128, then the highest bit of `x` is at least 128.\n        // solhint-disable no-inline-assembly\n        assembly {\n            // `f` is set to 1\u003c\u003c7 if `x \u003e= 2**128` and to 0 otherwise.\n            let f := shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\n            // If `x \u003e= 2**128` then set `msb` highest bit to 1 and shift `x` right by 128.\n            // Otherwise, `msb` remains 0 and `x` remains unchanged.\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        // `x` is now at most 2**128 - 1. Continue the same way, the next highest bit is 1\u003c\u003c6 == 64.\n        assembly {\n            // `f` is set to 1\u003c\u003c6 if `x \u003e= 2**64` and to 0 otherwise.\n            let f := shl(6, gt(x, 0xFFFFFFFFFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c5 if `x \u003e= 2**32` and to 0 otherwise.\n            let f := shl(5, gt(x, 0xFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c4 if `x \u003e= 2**16` and to 0 otherwise.\n            let f := shl(4, gt(x, 0xFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c3 if `x \u003e= 2**8` and to 0 otherwise.\n            let f := shl(3, gt(x, 0xFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c2 if `x \u003e= 2**4` and to 0 otherwise.\n            let f := shl(2, gt(x, 0xF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c1 if `x \u003e= 2**2` and to 0 otherwise.\n            let f := shl(1, gt(x, 0x3))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1 if `x \u003e= 2**1` and to 0 otherwise.\n            let f := gt(x, 0x1)\n            msb := or(msb, f)\n        }\n    }\n\n    /// @dev Wraps (mantissa, exponent) pair into Number.\n    function _encode(uint8 mantissa, uint8 exponent) private pure returns (Number) {\n        // Casts below are upcasts, so they are safe.\n        return Number.wrap(uint16(mantissa) \u003c\u003c SHIFT_MANTISSA | uint16(exponent));\n    }\n}\n\n// contracts/libs/stack/Request.sol\n\n/// Request is encoded data with \"message execution request\".\ntype Request is uint192;\n\nusing RequestLib for Request global;\n\n/// Library for formatting _the request part_ of _the base messages_.\n/// - Request represents a message sender requirements for the message execution on the destination chain.\n/// - Request occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n/// \u003e gasDrop field is included for future compatibility and is ignored at the moment.\n///\n/// # Request stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type   | Bytes | Description                                          |\n/// | ---------- | -------- | ------ | ----- | ---------------------------------------------------- |\n/// | (024..012] | gasDrop  | uint96 | 12    | Minimum amount of gas token to drop to the recipient |\n/// | (012..004] | gasLimit | uint64 | 8     | Minimum amount of gas units to supply for execution  |\n/// | (004..000] | version  | uint32 | 4     | Base message version to pass to the recipient        |\n\nlibrary RequestLib {\n    /// @dev Amount of bits to shift to gasDrop field\n    uint192 private constant SHIFT_GAS_DROP = 12 * 8;\n    /// @dev Amount of bits to shift to gasLimit field\n    uint192 private constant SHIFT_GAS_LIMIT = 4 * 8;\n\n    /// @notice Returns an encoded request with the given fields\n    /// @param gasDrop_     Minimum amount of gas token to drop to the recipient (ignored at the moment)\n    /// @param gasLimit_    Minimum amount of gas units to supply for execution\n    /// @param version_     Base message version to pass to the recipient\n    function encodeRequest(uint96 gasDrop_, uint64 gasLimit_, uint32 version_) internal pure returns (Request) {\n        // Casts below are upcasts, so they are safe\n        return Request.wrap(uint192(gasDrop_) \u003c\u003c SHIFT_GAS_DROP | uint192(gasLimit_) \u003c\u003c SHIFT_GAS_LIMIT | version_);\n    }\n\n    /// @notice Wraps the padded encoded request into a Request-typed value.\n    /// @dev The \"padded\" request is simply an encoded request casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded requests\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedRequest) internal pure returns (Request) {\n        // Casting to uint192 will truncate the highest bits, which is the behavior we want\n        return Request.wrap(uint192(paddedRequest));\n    }\n\n    /// @notice Returns the requested of gas token to drop to the recipient.\n    function gasDrop(Request request) internal pure returns (uint96) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return uint96(Request.unwrap(request) \u003e\u003e SHIFT_GAS_DROP);\n    }\n\n    /// @notice Returns the requested minimum amount of gas units to supply for execution.\n    function gasLimit(Request request) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Request.unwrap(request) \u003e\u003e SHIFT_GAS_LIMIT);\n    }\n\n    /// @notice Returns the requested base message version to pass to the recipient.\n    function version(Request request) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Request.unwrap(request));\n    }\n}\n\n// node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        require(value \u003c= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        require(value \u003c= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        require(value \u003c= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value \u003c= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        require(value \u003c= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        require(value \u003c= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        require(value \u003c= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        require(value \u003c= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        require(value \u003c= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        require(value \u003c= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        require(value \u003c= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        require(value \u003c= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        require(value \u003c= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        require(value \u003c= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        require(value \u003c= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value \u003c= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        require(value \u003c= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        require(value \u003c= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        require(value \u003c= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value \u003c= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        require(value \u003c= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        require(value \u003c= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        require(value \u003c= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value \u003c= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        require(value \u003c= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        require(value \u003c= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        require(value \u003c= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value \u003c= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        require(value \u003c= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value \u003c= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value \u003c= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     *\n     * _Available since v3.0._\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value \u003e= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     *\n     * _Available since v3.0._\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value \u003c= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     *\n     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length \u003e 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance \u003e= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance \u003e= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length \u003e 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n\n// contracts/base/MultiCallable.sol\n\n/// @notice Collection of Multicall utilities. Fork of Multicall3:\n/// https://github.com/mds1/multicall/blob/master/src/Multicall3.sol\nabstract contract MultiCallable {\n    struct Call {\n        bool allowFailure;\n        bytes callData;\n    }\n\n    struct Result {\n        bool success;\n        bytes returnData;\n    }\n\n    /// @notice Aggregates a few calls to this contract into one multicall without modifying `msg.sender`.\n    function multicall(Call[] calldata calls) external returns (Result[] memory callResults) {\n        uint256 amount = calls.length;\n        callResults = new Result[](amount);\n        Call calldata call_;\n        for (uint256 i = 0; i \u003c amount;) {\n            call_ = calls[i];\n            Result memory result = callResults[i];\n            // We perform a delegate call to ourselves here. Delegate call does not modify `msg.sender`, so\n            // this will have the same effect as if `msg.sender` performed all the calls themselves one by one.\n            // solhint-disable-next-line avoid-low-level-calls\n            (result.success, result.returnData) = address(this).delegatecall(call_.callData);\n            // solhint-disable-next-line no-inline-assembly\n            assembly {\n                // Revert if the call fails and failure is not allowed\n                // `allowFailure := calldataload(call_)` and `success := mload(result)`\n                if iszero(or(calldataload(call_), mload(result))) {\n                    // Revert with `0x4d6a2328` (function selector for `MulticallFailed()`)\n                    mstore(0x00, 0x4d6a232800000000000000000000000000000000000000000000000000000000)\n                    revert(0x00, 0x04)\n                }\n            }\n            unchecked {\n                ++i;\n            }\n        }\n    }\n}\n\n// contracts/base/Version.sol\n\n/**\n * @title Versioned\n * @notice Version getter for contracts. Doesn't use any storage slots, meaning\n * it will never cause any troubles with the upgradeable contracts. For instance, this contract\n * can be added or removed from the inheritance chain without shifting the storage layout.\n */\nabstract contract Versioned {\n    /**\n     * @notice Struct that is mimicking the storage layout of a string with 32 bytes or less.\n     * Length is limited by 32, so the whole string payload takes two memory words:\n     * @param length    String length\n     * @param data      String characters\n     */\n    struct _ShortString {\n        uint256 length;\n        bytes32 data;\n    }\n\n    /// @dev Length of the \"version string\"\n    uint256 private immutable _length;\n    /// @dev Bytes representation of the \"version string\".\n    /// Strings with length over 32 are not supported!\n    bytes32 private immutable _data;\n\n    constructor(string memory version_) {\n        _length = bytes(version_).length;\n        if (_length \u003e 32) revert IncorrectVersionLength();\n        // bytes32 is left-aligned =\u003e this will store the byte representation of the string\n        // with the trailing zeroes to complete the 32-byte word\n        _data = bytes32(bytes(version_));\n    }\n\n    function version() external view returns (string memory versionString) {\n        // Load the immutable values to form the version string\n        _ShortString memory str = _ShortString(_length, _data);\n        // The only way to do this cast is doing some dirty assembly\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            versionString := str\n        }\n    }\n}\n\n// contracts/libs/ChainContext.sol\n\n/// @notice Library for accessing chain context variables as tightly packed integers.\n/// Messaging contracts should rely on this library for accessing chain context variables\n/// instead of doing the casting themselves.\nlibrary ChainContext {\n    using SafeCast for uint256;\n\n    /// @notice Returns the current block number as uint40.\n    /// @dev Reverts if block number is greater than 40 bits, which is not supposed to happen\n    /// until the block.timestamp overflows (assuming block time is at least 1 second).\n    function blockNumber() internal view returns (uint40) {\n        return block.number.toUint40();\n    }\n\n    /// @notice Returns the current block timestamp as uint40.\n    /// @dev Reverts if block timestamp is greater than 40 bits, which is\n    /// supposed to happen approximately in year 36835.\n    function blockTimestamp() internal view returns (uint40) {\n        return block.timestamp.toUint40();\n    }\n\n    /// @notice Returns the chain id as uint32.\n    /// @dev Reverts if chain id is greater than 32 bits, which is not\n    /// supposed to happen in production.\n    function chainId() internal view returns (uint32) {\n        return block.chainid.toUint32();\n    }\n}\n\n// contracts/libs/Structures.sol\n\n// Here we define common enums and structures to enable their easier reusing later.\n\n// ═══════════════════════════════ AGENT STATUS ════════════════════════════════\n\n/// @dev Potential statuses for the off-chain bonded agent:\n/// - Unknown: never provided a bond =\u003e signature not valid\n/// - Active: has a bond in BondingManager =\u003e signature valid\n/// - Unstaking: has a bond in BondingManager, initiated the unstaking =\u003e signature not valid\n/// - Resting: used to have a bond in BondingManager, successfully unstaked =\u003e signature not valid\n/// - Fraudulent: proven to commit fraud, value in Merkle Tree not updated =\u003e signature not valid\n/// - Slashed: proven to commit fraud, value in Merkle Tree was updated =\u003e signature not valid\n/// Unstaked agent could later be added back to THE SAME domain by staking a bond again.\n/// Honest agent: Unknown -\u003e Active -\u003e unstaking -\u003e Resting -\u003e Active ...\n/// Malicious agent: Unknown -\u003e Active -\u003e Fraudulent -\u003e Slashed\n/// Malicious agent: Unknown -\u003e Active -\u003e Unstaking -\u003e Fraudulent -\u003e Slashed\nenum AgentFlag {\n    Unknown,\n    Active,\n    Unstaking,\n    Resting,\n    Fraudulent,\n    Slashed\n}\n\n/// @notice Struct for storing an agent in the BondingManager contract.\nstruct AgentStatus {\n    AgentFlag flag;\n    uint32 domain;\n    uint32 index;\n}\n// 184 bits available for tight packing\n\nusing StructureUtils for AgentStatus global;\n\n/// @notice Potential statuses of an agent in terms of being in dispute\n/// - None: agent is not in dispute\n/// - Pending: agent is in unresolved dispute\n/// - Slashed: agent was in dispute that lead to agent being slashed\n/// Note: agent who won the dispute has their status reset to None\nenum DisputeFlag {\n    None,\n    Pending,\n    Slashed\n}\n\n/// @notice Struct for storing dispute status of an agent.\n/// @param flag         Dispute flag: None/Pending/Slashed.\n/// @param openedAt     Timestamp when the latest agent dispute was opened (zero if not opened).\n/// @param resolvedAt   Timestamp when the latest agent dispute was resolved (zero if not resolved).\nstruct DisputeStatus {\n    DisputeFlag flag;\n    uint40 openedAt;\n    uint40 resolvedAt;\n}\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\n/// @notice Struct representing the status of Destination contract.\n/// @param snapRootTime     Timestamp when latest snapshot root was accepted\n/// @param agentRootTime    Timestamp when latest agent root was accepted\n/// @param notaryIndex      Index of Notary who signed the latest agent root\nstruct DestinationStatus {\n    uint40 snapRootTime;\n    uint40 agentRootTime;\n    uint32 notaryIndex;\n}\n\n// ═══════════════════════════════ EXECUTION HUB ═══════════════════════════════\n\n/// @notice Potential statuses of the message in Execution Hub.\n/// - None: there hasn't been a valid attempt to execute the message yet\n/// - Failed: there was a valid attempt to execute the message, but recipient reverted\n/// - Success: there was a valid attempt to execute the message, and recipient did not revert\n/// Note: message can be executed until its status is Success\nenum MessageStatus {\n    None,\n    Failed,\n    Success\n}\n\nlibrary StructureUtils {\n    /// @notice Checks that Agent is Active\n    function verifyActive(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active) {\n            revert AgentNotActive();\n        }\n    }\n\n    /// @notice Checks that Agent is Unstaking\n    function verifyUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Unstaking) {\n            revert AgentNotUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Active or Unstaking\n    function verifyActiveUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active \u0026\u0026 status.flag != AgentFlag.Unstaking) {\n            revert AgentNotActiveNorUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Fraudulent\n    function verifyFraudulent(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Fraudulent) {\n            revert AgentNotFraudulent();\n        }\n    }\n\n    /// @notice Checks that Agent is not Unknown\n    function verifyKnown(AgentStatus memory status) internal pure {\n        if (status.flag == AgentFlag.Unknown) {\n            revert AgentUnknown();\n        }\n    }\n}\n\n// contracts/libs/memory/MemView.sol\n\n/// @dev MemView is an untyped view over a portion of memory to be used instead of `bytes memory`\ntype MemView is uint256;\n\n/// @dev Attach library functions to MemView\nusing MemViewLib for MemView global;\n\n/// @notice Library for operations with the memory views.\n/// Forked from https://github.com/summa-tx/memview-sol with several breaking changes:\n/// - The codebase is ported to Solidity 0.8\n/// - Custom errors are added\n/// - The runtime type checking is replaced with compile-time check provided by User-Defined Value Types\n///   https://docs.soliditylang.org/en/latest/types.html#user-defined-value-types\n/// - uint256 is used as the underlying type for the \"memory view\" instead of bytes29.\n///   It is wrapped into MemView custom type in order not to be confused with actual integers.\n/// - Therefore the \"type\" field is discarded, allowing to allocate 16 bytes for both view location and length\n/// - The documentation is expanded\n/// - Library functions unused by the rest of the codebase are removed\n//  - Very pretty code separators are added :)\nlibrary MemViewLib {\n    /// @notice Stack layout for uint256 (from highest bits to lowest)\n    /// (32 .. 16]      loc     16 bytes    Memory address of underlying bytes\n    /// (16 .. 00]      len     16 bytes    Length of underlying bytes\n\n    // ═══════════════════════════════════════════ BUILDING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Instantiate a new untyped memory view. This should generally not be called directly.\n     * Prefer `ref` wherever possible.\n     * @param loc_          The memory address\n     * @param len_          The length\n     * @return The new view with the specified location and length\n     */\n    function build(uint256 loc_, uint256 len_) internal pure returns (MemView) {\n        uint256 end_ = loc_ + len_;\n        // Make sure that a view is not constructed that points to unallocated memory\n        // as this could be indicative of a buffer overflow attack\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            if gt(end_, mload(0x40)) { end_ := 0 }\n        }\n        if (end_ == 0) {\n            revert UnallocatedMemory();\n        }\n        return _unsafeBuildUnchecked(loc_, len_);\n    }\n\n    /**\n     * @notice Instantiate a memory view from a byte array.\n     * @dev Note that due to Solidity memory representation, it is not possible to\n     * implement a deref, as the `bytes` type stores its len in memory.\n     * @param arr           The byte array\n     * @return The memory view over the provided byte array\n     */\n    function ref(bytes memory arr) internal pure returns (MemView) {\n        uint256 len_ = arr.length;\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 loc_;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // We add 0x20, so that the view starts exactly where the array data starts\n            loc_ := add(arr, 0x20)\n        }\n        return build(loc_, len_);\n    }\n\n    // ════════════════════════════════════════════ CLONING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to the new memory.\n     * @param memView       The memory view\n     * @return arr          The cloned byte array\n     */\n    function clone(MemView memView) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        unchecked {\n            _unsafeCopyTo(memView, ptr + 0x20);\n        }\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 len_ = memView.len();\n        uint256 footprint_ = memView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    /**\n     * @notice Copies all views, joins them into a new bytearray.\n     * @param memViews      The memory views\n     * @return arr          The new byte array with joined data behind the given views\n     */\n    function join(MemView[] memory memViews) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        MemView newView;\n        unchecked {\n            newView = _unsafeJoin(memViews, ptr + 0x20);\n        }\n        uint256 len_ = newView.len();\n        uint256 footprint_ = newView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    // ══════════════════════════════════════════ INSPECTING MEMORY VIEW ═══════════════════════════════════════════════\n\n    /**\n     * @notice Returns the memory address of the underlying bytes.\n     * @param memView       The memory view\n     * @return loc_         The memory address\n     */\n    function loc(MemView memView) internal pure returns (uint256 loc_) {\n        // loc is stored in the highest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u003e\u003e 128;\n    }\n\n    /**\n     * @notice Returns the number of bytes of the view.\n     * @param memView       The memory view\n     * @return len_         The length of the view\n     */\n    function len(MemView memView) internal pure returns (uint256 len_) {\n        // len is stored in the lowest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u0026 type(uint128).max;\n    }\n\n    /**\n     * @notice Returns the endpoint of `memView`.\n     * @param memView       The memory view\n     * @return end_         The endpoint of `memView`\n     */\n    function end(MemView memView) internal pure returns (uint256 end_) {\n        // The endpoint never overflows uint128, let alone uint256, so we could use unchecked math here\n        unchecked {\n            return memView.loc() + memView.len();\n        }\n    }\n\n    /**\n     * @notice Returns the number of memory words this memory view occupies, rounded up.\n     * @param memView       The memory view\n     * @return words_       The number of memory words\n     */\n    function words(MemView memView) internal pure returns (uint256 words_) {\n        // returning ceil(length / 32.0)\n        unchecked {\n            return (memView.len() + 31) \u003e\u003e 5;\n        }\n    }\n\n    /**\n     * @notice Returns the in-memory footprint of a fresh copy of the view.\n     * @param memView       The memory view\n     * @return footprint_   The in-memory footprint of a fresh copy of the view.\n     */\n    function footprint(MemView memView) internal pure returns (uint256 footprint_) {\n        // words() * 32\n        return memView.words() \u003c\u003c 5;\n    }\n\n    // ════════════════════════════════════════════ HASHING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the keccak256 hash of the underlying memory\n     * @param memView       The memory view\n     * @return digest       The keccak256 hash of the underlying memory\n     */\n    function keccak(MemView memView) internal pure returns (bytes32 digest) {\n        uint256 loc_ = memView.loc();\n        uint256 len_ = memView.len();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            digest := keccak256(loc_, len_)\n        }\n    }\n\n    /**\n     * @notice Adds a salt to the keccak256 hash of the underlying data and returns the keccak256 hash of the\n     * resulting data.\n     * @param memView       The memory view\n     * @return digestSalted keccak256(salt, keccak256(memView))\n     */\n    function keccakSalted(MemView memView, bytes32 salt) internal pure returns (bytes32 digestSalted) {\n        return keccak256(bytes.concat(salt, memView.keccak()));\n    }\n\n    // ════════════════════════════════════════════ SLICING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Safe slicing without memory modification.\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the given index\n     */\n    function slice(MemView memView, uint256 index_, uint256 len_) internal pure returns (MemView) {\n        uint256 loc_ = memView.loc();\n        // Ensure it doesn't overrun the view\n        if (loc_ + index_ + len_ \u003e memView.end()) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // loc_ + index_ \u003c= memView.end()\n            return build({loc_: loc_ + index_, len_: len_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing bytes from `index` to end(memView).\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @return The new view for the slice starting from the given index until the initial view endpoint\n     */\n    function sliceFrom(MemView memView, uint256 index_) internal pure returns (MemView) {\n        uint256 len_ = memView.len();\n        // Ensure it doesn't overrun the view\n        if (index_ \u003e len_) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // index_ \u003c= len_ =\u003e memView.loc() + index_ \u003c= memView.loc() + memView.len() == memView.end()\n            return build({loc_: memView.loc() + index_, len_: len_ - index_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the first `len` bytes.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the initial view beginning\n     */\n    function prefix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        return memView.slice({index_: 0, len_: len_});\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the last `len` byte.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length until the initial view endpoint\n     */\n    function postfix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        uint256 viewLen = memView.len();\n        // Ensure it doesn't overrun the view\n        if (len_ \u003e viewLen) {\n            revert ViewOverrun();\n        }\n        // Could do the unchecked math due to the check above\n        uint256 index_;\n        unchecked {\n            index_ = viewLen - len_;\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // len_ \u003c= memView.len() =\u003e memView.loc() \u003c= loc_ \u003c= memView.end()\n            return build({loc_: memView.loc() + viewLen - len_, len_: len_});\n        }\n    }\n\n    // ═══════════════════════════════════════════ INDEXING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Load up to 32 bytes from the view onto the stack.\n     * @dev Returns a bytes32 with only the `bytes_` HIGHEST bytes set.\n     * This can be immediately cast to a smaller fixed-length byte array.\n     * To automatically cast to an integer, use `indexUint`.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return result       The 32 byte result having only `bytes_` highest bytes set\n     */\n    function index(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (bytes32 result) {\n        if (bytes_ == 0) {\n            return bytes32(0);\n        }\n        // Can't load more than 32 bytes to the stack in one go\n        if (bytes_ \u003e 32) {\n            revert IndexedTooMuch();\n        }\n        // The last indexed byte should be within view boundaries\n        if (index_ + bytes_ \u003e memView.len()) {\n            revert ViewOverrun();\n        }\n        uint256 bitLength = bytes_ \u003c\u003c 3; // bytes_ * 8\n        uint256 loc_ = memView.loc();\n        // Get a mask with `bitLength` highest bits set\n        uint256 mask;\n        // 0x800...00 binary representation is 100...00\n        // sar stands for \"signed arithmetic shift\": https://en.wikipedia.org/wiki/Arithmetic_shift\n        // sar(N-1, 100...00) = 11...100..00, with exactly N highest bits set to 1\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            mask := sar(sub(bitLength, 1), 0x8000000000000000000000000000000000000000000000000000000000000000)\n        }\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load a full word using index offset, and apply mask to ignore non-relevant bytes\n            result := and(mload(add(loc_, index_)), mask)\n        }\n    }\n\n    /**\n     * @notice Parse an unsigned integer from the view at `index`.\n     * @dev Requires that the view have \u003e= `bytes_` bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return The unsigned integer\n     */\n    function indexUint(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (uint256) {\n        bytes32 indexedBytes = memView.index(index_, bytes_);\n        // `index()` returns left-aligned `bytes_`, while integers are right-aligned\n        // Shifting here to right-align with the full 32 bytes word: need to shift right `(32 - bytes_)` bytes\n        unchecked {\n            // memView.index() reverts when bytes_ \u003e 32, thus unchecked math\n            return uint256(indexedBytes) \u003e\u003e ((32 - bytes_) \u003c\u003c 3);\n        }\n    }\n\n    /**\n     * @notice Parse an address from the view at `index`.\n     * @dev Requires that the view have \u003e= 20 bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @return The address\n     */\n    function indexAddress(MemView memView, uint256 index_) internal pure returns (address) {\n        // index 20 bytes as `uint160`, and then cast to `address`\n        return address(uint160(memView.indexUint(index_, 20)));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns a memory view over the specified memory location\n    /// without checking if it points to unallocated memory.\n    function _unsafeBuildUnchecked(uint256 loc_, uint256 len_) private pure returns (MemView) {\n        // There is no scenario where loc or len would overflow uint128, so we omit this check.\n        // We use the highest 128 bits to encode the location and the lowest 128 bits to encode the length.\n        return MemView.wrap((loc_ \u003c\u003c 128) | len_);\n    }\n\n    /**\n     * @notice Copy the view to a location, return an unsafe memory reference\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memView       The memory view\n     * @param newLoc        The new location to copy the underlying view data\n     * @return The memory view over the unsafe memory with the copied underlying data\n     */\n    function _unsafeCopyTo(MemView memView, uint256 newLoc) private view returns (MemView) {\n        uint256 len_ = memView.len();\n        uint256 oldLoc = memView.loc();\n\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (newLoc \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        bool res;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // use the identity precompile (0x04) to copy\n            res := staticcall(gas(), 0x04, oldLoc, len_, newLoc, len_)\n        }\n        if (!res) revert PrecompileOutOfGas();\n        return _unsafeBuildUnchecked({loc_: newLoc, len_: len_});\n    }\n\n    /**\n     * @notice Join the views in memory, return an unsafe reference to the memory.\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memViews      The memory views\n     * @return The conjoined view pointing to the new memory\n     */\n    function _unsafeJoin(MemView[] memory memViews, uint256 location) private view returns (MemView) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (location \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        // Copy the views to the specified location one by one, by tracking the amount of copied bytes so far\n        uint256 offset = 0;\n        for (uint256 i = 0; i \u003c memViews.length;) {\n            MemView memView = memViews[i];\n            // We can use the unchecked math here as location + sum(view.length) will never overflow uint256\n            unchecked {\n                _unsafeCopyTo(memView, location + offset);\n                offset += memView.len();\n                ++i;\n            }\n        }\n        return _unsafeBuildUnchecked({loc_: location, len_: offset});\n    }\n}\n\n// contracts/libs/merkle/MerkleMath.sol\n\nlibrary MerkleMath {\n    // ═════════════════════════════════════════ BASIC MERKLE CALCULATIONS ═════════════════════════════════════════════\n\n    /**\n     * @notice Calculates the merkle root for the given leaf and merkle proof.\n     * @dev Will revert if proof length exceeds the tree height.\n     * @param index     Index of `leaf` in tree\n     * @param leaf      Leaf of the merkle tree\n     * @param proof     Proof of inclusion of `leaf` in the tree\n     * @param height    Height of the merkle tree\n     * @return root_    Calculated Merkle Root\n     */\n    function proofRoot(uint256 index, bytes32 leaf, bytes32[] memory proof, uint256 height)\n        internal\n        pure\n        returns (bytes32 root_)\n    {\n        // Proof length could not exceed the tree height\n        uint256 proofLen = proof.length;\n        if (proofLen \u003e height) revert TreeHeightTooLow();\n        root_ = leaf;\n        /// @dev Apply unchecked to all ++h operations\n        unchecked {\n            // Go up the tree levels from the leaf following the proof\n            for (uint256 h = 0; h \u003c proofLen; ++h) {\n                // Get a sibling node on current level: this is proof[h]\n                root_ = getParent(root_, proof[h], index, h);\n            }\n            // Go up to the root: the remaining siblings are EMPTY\n            for (uint256 h = proofLen; h \u003c height; ++h) {\n                root_ = getParent(root_, bytes32(0), index, h);\n            }\n        }\n    }\n\n    /**\n     * @notice Calculates the parent of a node on the path from one of the leafs to root.\n     * @param node          Node on a path from tree leaf to root\n     * @param sibling       Sibling for a given node\n     * @param leafIndex     Index of the tree leaf\n     * @param nodeHeight    \"Level height\" for `node` (ZERO for leafs, ORIGIN_TREE_HEIGHT for root)\n     */\n    function getParent(bytes32 node, bytes32 sibling, uint256 leafIndex, uint256 nodeHeight)\n        internal\n        pure\n        returns (bytes32 parent)\n    {\n        // Index for `node` on its \"tree level\" is (leafIndex / 2**height)\n        // \"Left child\" has even index, \"right child\" has odd index\n        if ((leafIndex \u003e\u003e nodeHeight) \u0026 1 == 0) {\n            // Left child\n            return getParent(node, sibling);\n        } else {\n            // Right child\n            return getParent(sibling, node);\n        }\n    }\n\n    /// @notice Calculates the parent of tow nodes in the merkle tree.\n    /// @dev We use implementation with H(0,0) = 0\n    /// This makes EVERY empty node in the tree equal to ZERO,\n    /// saving us from storing H(0,0), H(H(0,0), H(0, 0)), and so on\n    /// @param leftChild    Left child of the calculated node\n    /// @param rightChild   Right child of the calculated node\n    /// @return parent      Value for the node having above mentioned children\n    function getParent(bytes32 leftChild, bytes32 rightChild) internal pure returns (bytes32 parent) {\n        if (leftChild == bytes32(0) \u0026\u0026 rightChild == bytes32(0)) {\n            return 0;\n        } else {\n            return keccak256(bytes.concat(leftChild, rightChild));\n        }\n    }\n\n    // ════════════════════════════════ ROOT/PROOF CALCULATION FOR A LIST OF LEAFS ═════════════════════════════════════\n\n    /**\n     * @notice Calculates merkle root for a list of given leafs.\n     * Merkle Tree is constructed by padding the list with ZERO values for leafs until list length is `2**height`.\n     * Merkle Root is calculated for the constructed tree, and then saved in `leafs[0]`.\n     * \u003e Note:\n     * \u003e - `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * \u003e - Caller is expected not to reuse `hashes` list after the call, and only use `leafs[0]` value,\n     * which is guaranteed to contain the calculated merkle root.\n     * \u003e - root is calculated using the `H(0,0) = 0` Merkle Tree implementation. See MerkleTree.sol for details.\n     * @dev Amount of leaves should be at most `2**height`\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param height    Height of the Merkle Tree to construct\n     */\n    function calculateRoot(bytes32[] memory hashes, uint256 height) internal pure {\n        uint256 levelLength = hashes.length;\n        // Amount of hashes could not exceed amount of leafs in tree with the given height\n        if (levelLength \u003e (1 \u003c\u003c height)) revert TreeHeightTooLow();\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\": the amount of iterations for the for loop above.\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n            }\n        }\n    }\n\n    /**\n     * @notice Generates a proof of inclusion of a leaf in the list. If the requested index is outside\n     * of the list range, generates a proof of inclusion for an empty leaf (proof of non-inclusion).\n     * The Merkle Tree is constructed by padding the list with ZERO values until list length is a power of two\n     * __AND__ index is in the extended list range. For example:\n     *  - `hashes.length == 6` and `0 \u003c= index \u003c= 7` will \"extend\" the list to 8 entries.\n     *  - `hashes.length == 6` and `7 \u003c index \u003c= 15` will \"extend\" the list to 16 entries.\n     * \u003e Note: `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * Caller is expected not to reuse `hashes` list after the call.\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param index     Leaf index to generate the proof for\n     * @return proof    Generated merkle proof\n     */\n    function calculateProof(bytes32[] memory hashes, uint256 index) internal pure returns (bytes32[] memory proof) {\n        // Use only meaningful values for the shortened proof\n        // Check if index is within the list range (we want to generates proofs for outside leafs as well)\n        uint256 height = getHeight(index \u003c hashes.length ? hashes.length : (index + 1));\n        proof = new bytes32[](height);\n        uint256 levelLength = hashes.length;\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Use sibling for the merkle proof; `index^1` is index of our sibling\n                proof[h] = (index ^ 1 \u003c levelLength) ? hashes[index ^ 1] : bytes32(0);\n\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\"\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n                // Traverse to parent node\n                index \u003e\u003e= 1;\n            }\n        }\n    }\n\n    /// @notice Returns the height of the tree having a given amount of leafs.\n    function getHeight(uint256 leafs) internal pure returns (uint256 height) {\n        uint256 amount = 1;\n        while (amount \u003c leafs) {\n            unchecked {\n                ++height;\n            }\n            amount \u003c\u003c= 1;\n        }\n    }\n}\n\n// contracts/libs/stack/GasData.sol\n\n/// GasData in encoded data with \"basic information about gas prices\" for some chain.\ntype GasData is uint96;\n\nusing GasDataLib for GasData global;\n\n/// ChainGas is encoded data with given chain's \"basic information about gas prices\".\ntype ChainGas is uint128;\n\nusing GasDataLib for ChainGas global;\n\n/// Library for encoding and decoding GasData and ChainGas structs.\n/// # GasData\n/// `GasData` is a struct to store the \"basic information about gas prices\", that could\n/// be later used to approximate the cost of a message execution, and thus derive the\n/// minimal tip values for sending a message to the chain.\n/// \u003e - `GasData` is supposed to be cached by `GasOracle` contract, allowing to store the\n/// \u003e approximates instead of the exact values, and thus save on storage costs.\n/// \u003e - For instance, if `GasOracle` only updates the values on +- 10% change, having an\n/// \u003e 0.4% error on the approximates would be acceptable.\n/// `GasData` is supposed to be included in the Origin's state, which are synced across\n/// chains using Agent-signed snapshots and attestations.\n/// ## GasData stack layout (from highest bits to lowest)\n///\n/// | Position   | Field        | Type   | Bytes | Description                                         |\n/// | ---------- | ------------ | ------ | ----- | --------------------------------------------------- |\n/// | (012..010] | gasPrice     | uint16 | 2     | Gas price for the chain (in Wei per gas unit)       |\n/// | (010..008] | dataPrice    | uint16 | 2     | Calldata price (in Wei per byte of content)         |\n/// | (008..006] | execBuffer   | uint16 | 2     | Tx fee safety buffer for message execution (in Wei) |\n/// | (006..004] | amortAttCost | uint16 | 2     | Amortized cost for attestation submission (in Wei)  |\n/// | (004..002] | etherPrice   | uint16 | 2     | Chain's Ether Price / Mainnet Ether Price (in BWAD) |\n/// | (002..000] | markup       | uint16 | 2     | Markup for the message execution (in BWAD)          |\n/// \u003e See Number.sol for more details on `Number` type and BWAD (binary WAD) math.\n///\n/// ## ChainGas stack layout (from highest bits to lowest)\n///\n/// | Position   | Field   | Type   | Bytes | Description      |\n/// | ---------- | ------- | ------ | ----- | ---------------- |\n/// | (016..004] | gasData | uint96 | 12    | Chain's gas data |\n/// | (004..000] | domain  | uint32 | 4     | Chain's domain   |\nlibrary GasDataLib {\n    /// @dev Amount of bits to shift to gasPrice field\n    uint96 private constant SHIFT_GAS_PRICE = 10 * 8;\n    /// @dev Amount of bits to shift to dataPrice field\n    uint96 private constant SHIFT_DATA_PRICE = 8 * 8;\n    /// @dev Amount of bits to shift to execBuffer field\n    uint96 private constant SHIFT_EXEC_BUFFER = 6 * 8;\n    /// @dev Amount of bits to shift to amortAttCost field\n    uint96 private constant SHIFT_AMORT_ATT_COST = 4 * 8;\n    /// @dev Amount of bits to shift to etherPrice field\n    uint96 private constant SHIFT_ETHER_PRICE = 2 * 8;\n\n    /// @dev Amount of bits to shift to gasData field\n    uint128 private constant SHIFT_GAS_DATA = 4 * 8;\n\n    // ═════════════════════════════════════════════════ GAS DATA ══════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded GasData struct with the given fields.\n    /// @param gasPrice_        Gas price for the chain (in Wei per gas unit)\n    /// @param dataPrice_       Calldata price (in Wei per byte of content)\n    /// @param execBuffer_      Tx fee safety buffer for message execution (in Wei)\n    /// @param amortAttCost_    Amortized cost for attestation submission (in Wei)\n    /// @param etherPrice_      Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n    /// @param markup_          Markup for the message execution (in BWAD)\n    function encodeGasData(\n        Number gasPrice_,\n        Number dataPrice_,\n        Number execBuffer_,\n        Number amortAttCost_,\n        Number etherPrice_,\n        Number markup_\n    ) internal pure returns (GasData) {\n        // Number type wraps uint16, so could safely be casted to uint96\n        // forgefmt: disable-next-item\n        return GasData.wrap(\n            uint96(Number.unwrap(gasPrice_)) \u003c\u003c SHIFT_GAS_PRICE |\n            uint96(Number.unwrap(dataPrice_)) \u003c\u003c SHIFT_DATA_PRICE |\n            uint96(Number.unwrap(execBuffer_)) \u003c\u003c SHIFT_EXEC_BUFFER |\n            uint96(Number.unwrap(amortAttCost_)) \u003c\u003c SHIFT_AMORT_ATT_COST |\n            uint96(Number.unwrap(etherPrice_)) \u003c\u003c SHIFT_ETHER_PRICE |\n            uint96(Number.unwrap(markup_))\n        );\n    }\n\n    /// @notice Wraps padded uint256 value into GasData struct.\n    function wrapGasData(uint256 paddedGasData) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(paddedGasData));\n    }\n\n    /// @notice Returns the gas price, in Wei per gas unit.\n    function gasPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_GAS_PRICE));\n    }\n\n    /// @notice Returns the calldata price, in Wei per byte of content.\n    function dataPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_DATA_PRICE));\n    }\n\n    /// @notice Returns the tx fee safety buffer for message execution, in Wei.\n    function execBuffer(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_EXEC_BUFFER));\n    }\n\n    /// @notice Returns the amortized cost for attestation submission, in Wei.\n    function amortAttCost(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_AMORT_ATT_COST));\n    }\n\n    /// @notice Returns the ratio of Chain's Ether Price / Mainnet Ether Price, in BWAD math.\n    function etherPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_ETHER_PRICE));\n    }\n\n    /// @notice Returns the markup for the message execution, in BWAD math.\n    function markup(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data)));\n    }\n\n    // ════════════════════════════════════════════════ CHAIN DATA ═════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded ChainGas struct with the given fields.\n    /// @param gasData_ Chain's gas data\n    /// @param domain_  Chain's domain\n    function encodeChainGas(GasData gasData_, uint32 domain_) internal pure returns (ChainGas) {\n        // GasData type wraps uint96, so could safely be casted to uint128\n        return ChainGas.wrap(uint128(GasData.unwrap(gasData_)) \u003c\u003c SHIFT_GAS_DATA | uint128(domain_));\n    }\n\n    /// @notice Wraps padded uint256 value into ChainGas struct.\n    function wrapChainGas(uint256 paddedChainGas) internal pure returns (ChainGas) {\n        // Casting to uint128 will truncate the highest bits, which is the behavior we want\n        return ChainGas.wrap(uint128(paddedChainGas));\n    }\n\n    /// @notice Returns the chain's gas data.\n    function gasData(ChainGas data) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(ChainGas.unwrap(data) \u003e\u003e SHIFT_GAS_DATA));\n    }\n\n    /// @notice Returns the chain's domain.\n    function domain(ChainGas data) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(ChainGas.unwrap(data));\n    }\n\n    /// @notice Returns the hash for the list of ChainGas structs.\n    function snapGasHash(ChainGas[] memory snapGas) internal pure returns (bytes32 snapGasHash_) {\n        // Use assembly to calculate the hash of the array without copying it\n        // ChainGas takes a single word of storage, thus ChainGas[] is stored in the following way:\n        // 0x00: length of the array, in words\n        // 0x20: first ChainGas struct\n        // 0x40: second ChainGas struct\n        // And so on...\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Find the location where the array data starts, we add 0x20 to skip the length field\n            let loc := add(snapGas, 0x20)\n            // Load the length of the array (in words).\n            // Shifting left 5 bits is equivalent to multiplying by 32: this converts from words to bytes.\n            let len := shl(5, mload(snapGas))\n            // Calculate the hash of the array\n            snapGasHash_ := keccak256(loc, len)\n        }\n    }\n}\n\n// contracts/libs/stack/Header.sol\n\n/// Header is encoded data with \"general routing information\".\ntype Header is uint136;\n\nusing HeaderLib for Header global;\n\n/// Types of messages supported by Origin-Destination\n/// - Base: message sent by protocol user, contains tips\n/// - Manager: message sent between AgentManager contracts located on different chains, no tips\nenum MessageFlag {\n    Base,\n    Manager\n}\n\nusing HeaderLib for MessageFlag global;\n\n/// Library for formatting _the header part_ of _the messages used by Origin and Destination_.\n/// - Header represents general information for routing a Message for Origin and Destination.\n/// - Header occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n///\n/// # Header stack layout (from highest bits to lowest)\n///\n/// | Position   | Field            | Type   | Bytes | Description                             |\n/// | ---------- | ---------------- | ------ | ----- | --------------------------------------- |\n/// | (017..016] | flag             | uint8  | 1     | Flag specifying the type of message     |\n/// | (016..012] | origin           | uint32 | 4     | Domain where message originated         |\n/// | (012..008] | nonce            | uint32 | 4     | Message nonce on the origin domain      |\n/// | (008..004] | destination      | uint32 | 4     | Domain where message will be executed   |\n/// | (004..000] | optimisticPeriod | uint32 | 4     | Optimistic period that will be enforced |\nlibrary HeaderLib {\n    /// @dev Amount of bits to shift to flag field\n    uint136 private constant SHIFT_FLAG = 16 * 8;\n    /// @dev Amount of bits to shift to origin field\n    uint136 private constant SHIFT_ORIGIN = 12 * 8;\n    /// @dev Amount of bits to shift to nonce field\n    uint136 private constant SHIFT_NONCE = 8 * 8;\n    /// @dev Amount of bits to shift to destination field\n    uint136 private constant SHIFT_DESTINATION = 4 * 8;\n\n    /// @notice Returns an encoded header with provided fields\n    /// @param origin_              Domain of origin chain\n    /// @param nonce_               Message nonce on origin chain\n    /// @param destination_         Domain of destination chain\n    /// @param optimisticPeriod_    Optimistic period for message execution\n    function encodeHeader(\n        MessageFlag flag_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint32 destination_,\n        uint32 optimisticPeriod_\n    ) internal pure returns (Header) {\n        // All casts below are upcasts, so they are safe\n        // forgefmt: disable-next-item\n        return Header.wrap(\n            uint136(uint8(flag_)) \u003c\u003c SHIFT_FLAG |\n            uint136(origin_) \u003c\u003c SHIFT_ORIGIN |\n            uint136(nonce_) \u003c\u003c SHIFT_NONCE |\n            uint136(destination_) \u003c\u003c SHIFT_DESTINATION |\n            uint136(optimisticPeriod_)\n        );\n    }\n\n    /// @notice Checks that the header is a valid encoded header.\n    function isHeader(uint256 paddedHeader) internal pure returns (bool) {\n        // Check that flag is within range\n        return _flag(paddedHeader) \u003c= uint8(type(MessageFlag).max);\n    }\n\n    /// @notice Wraps the padded encoded request into a Header-typed value.\n    /// @dev The \"padded\" header is simply an encoded header casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded headers\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedHeader) internal pure returns (Header) {\n        // Check that flag is within range\n        if (!isHeader(paddedHeader)) revert FlagOutOfRange();\n        // Casting to uint136 will truncate the highest bits, which is the behavior we want\n        return Header.wrap(uint136(paddedHeader));\n    }\n\n    /// @notice Returns header's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Header header) internal pure returns (bytes32 hashedHeader) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store header in scratch space\n            mstore(0, header)\n            // Compute hash of header padded to 32 bytes\n            hashedHeader := keccak256(0, 32)\n        }\n    }\n\n    // ══════════════════════════════════════════════ HEADER SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns header's flag field\n    function flag(Header header) internal pure returns (MessageFlag) {\n        // We check that flag is within range when wrapping the header, so this cast is safe\n        return MessageFlag(_flag(Header.unwrap(header)));\n    }\n\n    /// @notice Returns header's origin field\n    function origin(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_ORIGIN);\n    }\n\n    /// @notice Returns header's nonce field\n    function nonce(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_NONCE);\n    }\n\n    /// @notice Returns header's destination field\n    function destination(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_DESTINATION);\n    }\n\n    /// @notice Returns header's optimistic seconds field\n    function optimisticPeriod(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns header's flag field without casting to MessageFlag\n    function _flag(uint256 paddedHeader) private pure returns (uint8) {\n        // Casting to uint8 will truncate the highest bits, which is the behavior we want\n        return uint8(paddedHeader \u003e\u003e SHIFT_FLAG);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n     * constructor.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall \u0026\u0026 _initialized \u003c 1) || (!AddressUpgradeable.isContract(address(this)) \u0026\u0026 _initialized == 1),\n            \"Initializable: contract is already initialized\"\n        );\n        _initialized = 1;\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: setting the version to 255 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing \u0026\u0026 _initialized \u003c version, \"Initializable: contract is already initialized\");\n        _initialized = version;\n        _initializing = true;\n        _;\n        _initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        require(_initializing, \"Initializable: contract is not initializing\");\n        _;\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized != type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint8) {\n        return _initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _initializing;\n    }\n}\n\n// contracts/interfaces/IAgentManager.sol\n\ninterface IAgentManager {\n    /**\n     * @notice Allows Inbox to open a Dispute between a Guard and a Notary, if they are both not in Dispute already.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Guard or Notary is already in Dispute.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Allows Inbox to slash an agent, if their fraud was proven.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Domain doesn't match the saved agent domain.\n     * @param domain    Domain where the Agent is active\n     * @param agent     Address of the Agent\n     * @param prover    Address that initially provided fraud proof\n     */\n    function slashAgent(uint32 domain, address agent, address prover) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest known root of the Agent Merkle Tree.\n     */\n    function agentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns the number of opened Disputes.\n     * @dev This includes the Disputes that have been resolved already.\n     */\n    function getDisputesAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns information about the dispute with the given index.\n     * @dev Will revert if dispute with given index hasn't been opened yet.\n     * @param index             Dispute index\n     * @return guard            Address of the Guard in the Dispute\n     * @return notary           Address of the Notary in the Dispute\n     * @return slashedAgent     Address of the Agent who was slashed when Dispute was resolved\n     * @return fraudProver      Address who provided fraud proof to resolve the Dispute\n     * @return reportPayload    Raw payload with report data that led to the Dispute\n     * @return reportSignature  Guard signature for the report payload\n     */\n    function getDispute(uint256 index)\n        external\n        view\n        returns (\n            address guard,\n            address notary,\n            address slashedAgent,\n            address fraudProver,\n            bytes memory reportPayload,\n            bytes memory reportSignature\n        );\n\n    /**\n     * @notice Returns the current Dispute status of a given agent. See Structures.sol for details.\n     * @dev Every returned value will be set to zero if agent was not slashed and is not in Dispute.\n     * `rival` and `disputePtr` will be set to zero if the agent was slashed without being in Dispute.\n     * @param agent         Agent address\n     * @return flag         Flag describing the current Dispute status for the agent: None/Pending/Slashed\n     * @return rival        Address of the rival agent in the Dispute\n     * @return fraudProver  Address who provided fraud proof to resolve the Dispute\n     * @return disputePtr   Index of the opened Dispute PLUS ONE. Zero if agent is not in Dispute.\n     */\n    function disputeStatus(address agent)\n        external\n        view\n        returns (DisputeFlag flag, address rival, address fraudProver, uint256 disputePtr);\n}\n\n// contracts/interfaces/IAgentSecured.sol\n\ninterface IAgentSecured {\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * between a Guard and a Notary has been opened.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * has been resolved due to one of the agents being slashed.\n     * \u003e `rivalIndex` will be ZERO, if the slashed agent was not in the Dispute.\n     * @param slashedIndex  Index of the slashed agent in the Agent Merkle Tree\n     * @param rivalIndex    Index of the their Dispute Rival in the Agent Merkle Tree\n     */\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the address of the local AgentManager contract, which is treated as\n     * the \"source of truth\" for agent statuses.\n     */\n    function agentManager() external view returns (address);\n\n    /**\n     * @notice Returns the address of the local Inbox contract, which is treated as\n     * the \"source of truth\" for agent-signed statements.\n     * @dev Inbox passes verified agent statements to `IAgentSecured` contract.\n     */\n    function inbox() external view returns (address);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns (flag, openedAt, resolvedAt) that describes the latest status of\n     * the latest dispute for an agent with a given index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param agentIndex    Agent index in the Agent Merkle Tree\n     * @return              Latest dispute status for the given agent: (flag, openedAt, resolvedAt)\n     */\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory);\n}\n\n// contracts/libs/memory/ByteString.sol\n\n/// @dev CallData is a memory view over the payload to be used for an external call, i.e.\n/// recipient.call(callData). Its length is always (4 + 32 * N) bytes:\n/// - First 4 bytes represent the function selector.\n/// - 32 * N bytes represent N words that function arguments occupy.\ntype CallData is uint256;\n\n/// @dev Attach library functions to CallData\nusing ByteString for CallData global;\n\n/// @dev Signature is a memory view over a \"65 bytes\" array representing a ECDSA signature.\ntype Signature is uint256;\n\n/// @dev Attach library functions to Signature\nusing ByteString for Signature global;\n\nlibrary ByteString {\n    using MemViewLib for bytes;\n\n    /**\n     * @dev non-compact ECDSA signatures are enforced as of OZ 4.7.3\n     *\n     *      Signature payload memory layout\n     * [000 .. 032) r   bytes32 32 bytes\n     * [032 .. 064) s   bytes32 32 bytes\n     * [064 .. 065) v   uint8    1 byte\n     */\n    uint256 internal constant SIGNATURE_LENGTH = 65;\n    uint256 private constant OFFSET_R = 0;\n    uint256 private constant OFFSET_S = 32;\n    uint256 private constant OFFSET_V = 64;\n\n    /**\n     * @dev Calldata memory layout\n     * [000 .. 004) selector    bytes4  4 bytes\n     *      Optional: N function arguments\n     * [004 .. 036) arg1        bytes32 32 bytes\n     *      ..\n     * [AAA .. END) argN        bytes32 32 bytes\n     */\n    uint256 internal constant SELECTOR_LENGTH = 4;\n    uint256 private constant OFFSET_SELECTOR = 0;\n    uint256 private constant OFFSET_ARGUMENTS = SELECTOR_LENGTH;\n\n    // ═════════════════════════════════════════════════ SIGNATURE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the signature payload from the given values.\n     * @dev Using ByteString.formatSignature({r: r, s: s, v: v}) will make sure\n     * that params are given in the right order.\n     */\n    function formatSignature(bytes32 r, bytes32 s, uint8 v) internal pure returns (bytes memory) {\n        return abi.encodePacked(r, s, v);\n    }\n\n    /**\n     * @notice Returns a Signature view over for the given payload.\n     * @dev Will revert if the payload is not a signature.\n     */\n    function castToSignature(bytes memory payload) internal pure returns (Signature) {\n        return castToSignature(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Signature view.\n     * @dev Will revert if the memory view is not over a signature.\n     */\n    function castToSignature(MemView memView) internal pure returns (Signature) {\n        if (!isSignature(memView)) revert UnformattedSignature();\n        return Signature.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a signature\n     */\n    function isSignature(MemView memView) internal pure returns (bool) {\n        return memView.len() == SIGNATURE_LENGTH;\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Signature signature) internal pure returns (MemView) {\n        return MemView.wrap(Signature.unwrap(signature));\n    }\n\n    // ═════════════════════════════════════════════ SIGNATURE SLICING ═════════════════════════════════════════════════\n\n    /// @notice Unpacks signature payload into (r, s, v) parameters.\n    /// @dev Make sure to verify signature length with isSignature() beforehand.\n    function toRSV(Signature signature) internal pure returns (bytes32 r, bytes32 s, uint8 v) {\n        // Get the underlying memory view\n        MemView memView = unwrap(signature);\n        r = memView.index({index_: OFFSET_R, bytes_: 32});\n        s = memView.index({index_: OFFSET_S, bytes_: 32});\n        // Can be safely casted to uint8, since we index a single byte\n        v = uint8(memView.indexUint({index_: OFFSET_V, bytes_: 1}));\n    }\n\n    // ═════════════════════════════════════════════════ CALLDATA ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the calldata with the modified arguments:\n     * the existing arguments are prepended with the arguments from the prefix.\n     * @dev Given:\n     *  - `calldata = abi.encodeWithSelector(foo.selector, d, e);`\n     *  - `prefix = abi.encode(a, b, c);`\n     *  - `a`, `b`, `c` are arguments of static type (i.e. not dynamically sized ones)\n     *      Then:\n     *  - Function will return abi.encodeWithSelector(foo.selector, a, c, c, d, e)\n     *  - Returned calldata will trigger `foo(a, b, c, d, e)` when used for a contract call.\n     * Note: for clarification as to what types are considered static, see\n     * https://docs.soliditylang.org/en/latest/abi-spec.html#formal-specification-of-the-encoding\n     * @param callData  Calldata that needs to be modified\n     * @param prefix    ABI-encoded arguments to use as the first arguments in the new calldata\n     * @return Modified calldata having prefix as the first arguments.\n     */\n    function addPrefix(CallData callData, bytes memory prefix) internal view returns (bytes memory) {\n        // Prefix should occupy a whole amount of words in memory\n        if (!_fullWords(prefix.length)) revert UnformattedCallDataPrefix();\n        MemView[] memory views = new MemView[](3);\n        // Use payload's function selector\n        views[0] = abi.encodePacked(callData.callSelector()).ref();\n        // Use prefix as the first arguments\n        views[1] = prefix.ref();\n        // Use payload's remaining arguments\n        views[2] = callData.arguments();\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a CallData view over for the given payload.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(bytes memory payload) internal pure returns (CallData) {\n        return castToCallData(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a CallData view.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(MemView memView) internal pure returns (CallData) {\n        if (!isCallData(memView)) revert UnformattedCallData();\n        return CallData.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a valid calldata, i.e.\n     * a function selector, followed by arbitrary amount of arguments.\n     */\n    function isCallData(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Calldata should at least have a function selector\n        if (length \u003c SELECTOR_LENGTH) return false;\n        // The remainder of the calldata should be exactly N memory words (N \u003e= 0)\n        return _fullWords(length - SELECTOR_LENGTH);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(CallData callData) internal pure returns (MemView) {\n        return MemView.wrap(CallData.unwrap(callData));\n    }\n\n    /// @notice Returns callData's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(CallData callData) internal pure returns (bytes32) {\n        return callData.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ CALLDATA SLICING ══════════════════════════════════════════════════\n\n    /**\n     * @notice Returns amount of memory words (32 byte chunks) the function arguments\n     * occupy in the calldata.\n     * @dev This might differ from amount of arguments supplied, if any of the arguments\n     * occupies more than one memory slot. It is true, however, that argument part of the payload\n     * occupies exactly N words, even for dynamic types like `bytes`\n     */\n    function argumentWords(CallData callData) internal pure returns (uint256) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        // Equivalent of (length - SELECTOR_LENGTH) / 32\n        return (memView.len() - SELECTOR_LENGTH) \u003e\u003e 5;\n    }\n\n    /// @notice Returns selector for the provided calldata.\n    function callSelector(CallData callData) internal pure returns (bytes4) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return bytes4(memView.index({index_: OFFSET_SELECTOR, bytes_: SELECTOR_LENGTH}));\n    }\n\n    /// @notice Returns abi encoded arguments for the provided calldata.\n    function arguments(CallData callData) internal pure returns (MemView) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return memView.sliceFrom({index_: OFFSET_ARGUMENTS});\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if length is full amount of memory words (32 bytes).\n    function _fullWords(uint256 length) internal pure returns (bool) {\n        // The equivalent of length % 32 == 0\n        return length \u0026 31 == 0;\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n    function __Context_init() internal onlyInitializing {\n    }\n\n    function __Context_init_unchained() internal onlyInitializing {\n    }\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[50] private __gap;\n}\n\n// contracts/libs/merkle/MerkleTree.sol\n\n/// `BaseTree` is a struct representing incremental merkle tree.\n/// - Contains only the current branch.\n/// - The number of inserted leaves is stored externally, and is later supplied for tree operations.\n/// - Has a fixed height of `ORIGIN_TREE_HEIGHT`.\n/// - Can store up to `2 ** ORIGIN_TREE_HEIGHT - 1` leaves.\n/// \u003e Note: the hash function for the tree `H(x, y)` is defined as:\n/// \u003e - `H(0,0) = 0`\n/// \u003e - `H(x,y) = keccak256(x, y), when (x != 0 || y != 0)`\n/// ## Invariant for leafs\n/// - The leftmost empty leaf has `index == count`, where `count` is the amount of the inserted leafs so far.\n/// - Value for any empty leaf or node is bytes32(0).\n/// ## Invariant for current branch\n/// `branch[i]` is always the value of a node on the i-th level.\n/// Levels are numbered from leafs to root: `0 .. ORIGIN_TREE_HEIGHT`.\n/// `branch[i]` stores the value for the node, such that:\n//  - The node is a \"left child\" (e.g. has an even index).\n/// - The node must have two non-empty children.\n/// - Out of all level's \"left child\" nodes with \"non-empty children\",\n/// the one with the biggest index (the rightmost one) is stored as `branch[i]`.\n/// \u003e __`branch` could be used to form a proof of inclusion for the first empty leaf (`index == count`).__\n/// _Here is how:_\n/// - Let's walk along the path from the \"first empty leaf\" to the root.\n/// - i-th bit of the \"first empty leaf\" index (which is equal to `count`) determines if the path's node\n/// for this i-th level is a \"left child\" or a \"right child\".\n/// - i-th bit in `count` is 0 → we are the left child on this level → sibling is the right child\n/// that does not exist yet → `proof[i] = bytes32(0)`.\n/// - i-th bit in `count` is 1 → we are the right child on this level → sibling is the left child\n/// sibling is the rightmost \"left child\" node on the level → `proof[i] = branch[i]`.\n/// \u003e Therefore `proof[i] = (count \u0026 (1 \u003c\u003c i)) == 0 ? bytes32(0) : branch[i])`\nstruct BaseTree {\n    bytes32[ORIGIN_TREE_HEIGHT] branch;\n}\n\nusing MerkleTree for BaseTree global;\n\n/// `HistoricalTree` is an incremental merkle tree keeping track of its historical merkle roots.\n/// \u003e - `roots[N]` is the root of the tree after `N` leafs were inserted\n/// \u003e - `roots[0] == bytes32(0)`\n/// @param tree     Incremental merkle tree\n/// @param roots    Historical merkle roots of the tree\nstruct HistoricalTree {\n    BaseTree tree;\n    bytes32[] roots;\n}\n\nusing MerkleTree for HistoricalTree global;\n\n/// `DynamicTree` is a struct representing a Merkle Tree with `2**AGENT_TREE_HEIGHT` leaves.\n/// - A single operation is available: update value for leaf with an arbitrary index (which might be a non-empty leaf).\n/// - This is done by requesting the proof of inclusion for the old value, which is used to both\n/// verify the old value, and calculate the new root.\n/// \u003e Based on Original idea from [ER forum post](https://ethresear.ch/t/efficient-on-chain-dynamic-merkle-tree/11054).\nstruct DynamicTree {\n    bytes32 root;\n}\n\nusing MerkleTree for DynamicTree global;\n\n/// MerkleTree is work based on Nomad's Merkle.sol, which is used under MIT OR Apache-2.0\n/// [link](https://github.com/nomad-xyz/monorepo/blob/main/packages/contracts-core/contracts/libs/Merkle.sol).\n/// With the following changes:\n/// - Adapted for Solidity 0.8.x.\n/// - Amount of tree leaves stored externally.\n/// - Added thorough documentation.\n/// - `H(0,0) = 0` optimization from [ER forum post](https://ethresear.ch/t/optimizing-sparse-merkle-trees/3751/6).\n/// \u003e Nomad's Merkle.sol is work based on eth2 deposit contract, which is used under CC0-1.0\n///[link](https://github.com/ethereum/deposit_contract/blob/dev/deposit_contract/contracts/validator_registration.v.py).\n/// With the following changes:\n/// \u003e - Implemented in Solidity 0.7.6 (eth2 deposit contract implemented in Vyper).\n/// \u003e - `H() = keccak256()` is used as the hashing function instead of `sha256()`.\nlibrary MerkleTree {\n    /// @dev For root calculation we need at least one empty leaf, thus the minus one in the formula.\n    uint256 internal constant MAX_LEAVES = 2 ** ORIGIN_TREE_HEIGHT - 1;\n\n    // ═════════════════════════════════════════════════ BASE TREE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Inserts `node` into merkle tree\n     * @dev Reverts if tree is full\n     * @param newCount  Amount of inserted leaves in the tree after the insertion (i.e. current + 1)\n     * @param node      Element to insert into tree\n     */\n    function insertBase(BaseTree storage tree, uint256 newCount, bytes32 node) internal {\n        if (newCount \u003e MAX_LEAVES) revert MerkleTreeFull();\n        // We go up the tree following the branch from the empty leaf AFTER the just inserted one.\n        // We stop when we find the first \"right child\" node.\n        // Its sibling is now the rightmost \"left child\" node that has two non-empty children.\n        // Therefore we need to update `tree.branch` value on this level.\n        // One could see that `tree.branch` value on lower and higher levels remain unchanged.\n\n        // Loop invariant: `node` is the current level's value for the branch from JUST INSERTED leaf\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            if ((newCount \u0026 1) == 1) {\n                // Found the first \"right child\" node on the branch from EMPTY leaf\n                // `node` is the value for node on branch from JUST INSERTED leaf\n                // Which in this case is the \"left child\".\n                // We update tree.branch and exit\n                tree.branch[i] = node;\n                return;\n            }\n            // On the branch from EMPTY leaf this is still a \"left child\".\n            // Meaning on branch from JUST INSERTED leaf, `node` is a right child.\n            // We compute value for `node` parent using `tree.branch` invariant:\n            // This is the rightmost \"left child\" node, which would be sibling of `node`.\n            node = MerkleMath.getParent(tree.branch[i], node);\n            // Get the parent index, and go to the next tree level\n            newCount \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n        // As the loop should always end prematurely with the `return` statement,\n        // this code should be unreachable. We assert `false` just to be safe.\n        assert(false);\n    }\n\n    /**\n     * @notice Calculates and returns current root of the merkle tree.\n     * @param count     Current amount of inserted leaves in the tree\n     * @return current  Calculated root of `tree`\n     */\n    function rootBase(BaseTree storage tree, uint256 count) internal view returns (bytes32 current) {\n        // To calculate the root we follow the branch of first EMPTY leaf (index == count)\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            // Check if we are the left or the right child on the current level\n            if ((count \u0026 1) == 1) {\n                // We are the right child. Our sibling is the \"rightmost\" \"left-child\" node\n                // that has two non-empty children → sibling is `tree.branch[i]`\n                current = MerkleMath.getParent(tree.branch[i], current);\n            } else {\n                // We are the left child. Our sibling does not exist yet → sibling is EMPTY\n                current = MerkleMath.getParent(current, bytes32(0));\n            }\n            // Get the parent index, and go to the next tree level\n            count \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    // ══════════════════════════════════════════════ HISTORICAL TREE ══════════════════════════════════════════════════\n\n    /// @notice Initializes the historical roots for the tree by inserting an empty root.\n    // solhint-disable-next-line ordering\n    function initializeRoots(HistoricalTree storage tree) internal returns (bytes32 savedRoot) {\n        // This should only be called once, when the contract is initialized\n        assert(tree.roots.length == 0);\n        // Save root for empty merkle tree: bytes32(0)\n        tree.roots.push(savedRoot);\n    }\n\n    /// @notice Inserts a new leaf into the merkle tree.\n    /// @dev Reverts if tree is full.\n    /// @param node         Element to insert into tree\n    /// @return newRoot     Merkle root after the leaf was inserted\n    function insert(HistoricalTree storage tree, bytes32 node) internal returns (bytes32 newRoot) {\n        // Tree count after the new leaf will be inserted (we store roots[0] as root of empty tree)\n        uint256 newCount = tree.roots.length;\n        tree.tree.insertBase(newCount, node);\n        // Save the new root\n        newRoot = tree.tree.rootBase(newCount);\n        tree.roots.push(newRoot);\n    }\n\n    /// @notice Returns the historical root of the merkle tree.\n    /// @dev Reverts if not enough leafs have been inserted.\n    /// @param count            Amount of leafs in the tree at some point of time\n    /// @return historicalRoot  Merkle root after `count` leafs were inserted\n    function root(HistoricalTree storage tree, uint256 count) internal view returns (bytes32 historicalRoot) {\n        if (count \u003e= tree.roots.length) revert NotEnoughLeafs();\n        return tree.roots[count];\n    }\n\n    // ═══════════════════════════════════════════════ DYNAMIC TREE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Updates the value for the leaf with the given index in the Dynamic Merkle Tree.\n     * @dev Will revert if incorrect proof of inclusion for old value is supplied.\n     * @param tree          Dynamic merkle tree\n     * @param index         Index of the leaf to update\n     * @param oldValue      Previous value of the leaf\n     * @param branch        Proof of inclusion of previous value into the tree\n     * @param newValue      New leaf value to assign\n     * @return newRoot      New value for the Merkle Root after the leaf is updated\n     */\n    function update(\n        DynamicTree storage tree,\n        uint256 index,\n        bytes32 oldValue,\n        bytes32[] memory branch,\n        bytes32 newValue\n    ) internal returns (bytes32 newRoot) {\n        // Check that the old value + proof result in a correct root\n        if (MerkleMath.proofRoot(index, oldValue, branch, AGENT_TREE_HEIGHT) != tree.root) {\n            revert LeafNotProven();\n        }\n        // New root is new value + the same proof (values for sibling nodes are not updated)\n        newRoot = MerkleMath.proofRoot(index, newValue, branch, AGENT_TREE_HEIGHT);\n        // Write the new root\n        tree.root = newRoot;\n    }\n}\n\n// contracts/libs/stack/Tips.sol\n\n/// Tips is encoded data with \"tips paid for sending a base message\".\n/// Note: even though uint256 is also an underlying type for MemView, Tips is stored ON STACK.\ntype Tips is uint256;\n\nusing TipsLib for Tips global;\n\n/// # Tips\n/// Library for formatting _the tips part_ of _the base messages_.\n///\n/// ## How the tips are awarded\n/// Tips are paid for sending a base message, and are split across all the agents that\n/// made the message execution on destination chain possible.\n/// ### Summit tips\n/// Split between:\n///     - Guard posting a snapshot with state ST_G for the origin chain.\n///     - Notary posting a snapshot SN_N using ST_G. This creates attestation A.\n///     - Notary posting a message receipt after it is executed on destination chain.\n/// ### Attestation tips\n/// Paid to:\n///     - Notary posting attestation A to destination chain.\n/// ### Execution tips\n/// Paid to:\n///     - First executor performing a valid execution attempt (correct proofs, optimistic period over),\n///      using attestation A to prove message inclusion on origin chain, whether the recipient reverted or not.\n/// ### Delivery tips.\n/// Paid to:\n///     - Executor who successfully executed the message on destination chain.\n///\n/// ## Tips encoding\n/// - Tips occupy a single storage word, and thus are stored on stack instead of being stored in memory.\n/// - The actual tip values should be determined by multiplying stored values by divided by TIPS_MULTIPLIER=2**32.\n/// - Tips are packed into a single word of storage, while allowing real values up to ~8*10**28 for every tip category.\n/// \u003e The only downside is that the \"real tip values\" are now multiplies of ~4*10**9, which should be fine even for\n/// the chains with the most expensive gas currency.\n/// # Tips stack layout (from highest bits to lowest)\n///\n/// | Position   | Field          | Type   | Bytes | Description                                                |\n/// | ---------- | -------------- | ------ | ----- | ---------------------------------------------------------- |\n/// | (032..024] | summitTip      | uint64 | 8     | Tip for agents interacting with Summit contract            |\n/// | (024..016] | attestationTip | uint64 | 8     | Tip for Notary posting attestation to Destination contract |\n/// | (016..008] | executionTip   | uint64 | 8     | Tip for valid execution attempt on destination chain       |\n/// | (008..000] | deliveryTip    | uint64 | 8     | Tip for successful message delivery on destination chain   |\n\nlibrary TipsLib {\n    using SafeCast for uint256;\n\n    /// @dev Amount of bits to shift to summitTip field\n    uint256 private constant SHIFT_SUMMIT_TIP = 24 * 8;\n    /// @dev Amount of bits to shift to attestationTip field\n    uint256 private constant SHIFT_ATTESTATION_TIP = 16 * 8;\n    /// @dev Amount of bits to shift to executionTip field\n    uint256 private constant SHIFT_EXECUTION_TIP = 8 * 8;\n\n    // ═══════════════════════════════════════════════════ TIPS ════════════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips with the given fields\n    /// @param summitTip_        Tip for agents interacting with Summit contract, divided by TIPS_MULTIPLIER\n    /// @param attestationTip_   Tip for Notary posting attestation to Destination contract, divided by TIPS_MULTIPLIER\n    /// @param executionTip_     Tip for valid execution attempt on destination chain, divided by TIPS_MULTIPLIER\n    /// @param deliveryTip_      Tip for successful message delivery on destination chain, divided by TIPS_MULTIPLIER\n    function encodeTips(uint64 summitTip_, uint64 attestationTip_, uint64 executionTip_, uint64 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // forgefmt: disable-next-item\n        return Tips.wrap(\n            uint256(summitTip_) \u003c\u003c SHIFT_SUMMIT_TIP |\n            uint256(attestationTip_) \u003c\u003c SHIFT_ATTESTATION_TIP |\n            uint256(executionTip_) \u003c\u003c SHIFT_EXECUTION_TIP |\n            uint256(deliveryTip_)\n        );\n    }\n\n    /// @notice Convenience function to encode tips with uint256 values.\n    function encodeTips256(uint256 summitTip_, uint256 attestationTip_, uint256 executionTip_, uint256 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // In practice, the tips amounts are not supposed to be higher than 2**96, and with 32 bits of granularity\n        // using uint64 is enough to store the values. However, we still check for overflow just in case.\n        // TODO: consider using Number type to store the tips values.\n        return encodeTips({\n            summitTip_: (summitTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            attestationTip_: (attestationTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            executionTip_: (executionTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            deliveryTip_: (deliveryTip_ \u003e\u003e TIPS_GRANULARITY).toUint64()\n        });\n    }\n\n    /// @notice Wraps the padded encoded tips into a Tips-typed value.\n    /// @dev There is no actual padding here, as the underlying type is already uint256,\n    /// but we include this function for consistency and to be future-proof, if tips will eventually use anything\n    /// smaller than uint256.\n    function wrapPadded(uint256 paddedTips) internal pure returns (Tips) {\n        return Tips.wrap(paddedTips);\n    }\n\n    /**\n     * @notice Returns a formatted Tips payload specifying empty tips.\n     * @return Formatted tips\n     */\n    function emptyTips() internal pure returns (Tips) {\n        return Tips.wrap(0);\n    }\n\n    /// @notice Returns tips's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Tips tips) internal pure returns (bytes32 hashedTips) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store tips in scratch space\n            mstore(0, tips)\n            // Compute hash of tips padded to 32 bytes\n            hashedTips := keccak256(0, 32)\n        }\n    }\n\n    // ═══════════════════════════════════════════════ TIPS SLICING ════════════════════════════════════════════════════\n\n    /// @notice Returns summitTip field\n    function summitTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_SUMMIT_TIP);\n    }\n\n    /// @notice Returns attestationTip field\n    function attestationTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_ATTESTATION_TIP);\n    }\n\n    /// @notice Returns executionTip field\n    function executionTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_EXECUTION_TIP);\n    }\n\n    /// @notice Returns deliveryTip field\n    function deliveryTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips));\n    }\n\n    // ════════════════════════════════════════════════ TIPS VALUE ═════════════════════════════════════════════════════\n\n    /// @notice Returns total value of the tips payload.\n    /// This is the sum of the encoded values, scaled up by TIPS_MULTIPLIER\n    function value(Tips tips) internal pure returns (uint256 value_) {\n        value_ = uint256(tips.summitTip()) + tips.attestationTip() + tips.executionTip() + tips.deliveryTip();\n        value_ \u003c\u003c= TIPS_GRANULARITY;\n    }\n\n    /// @notice Increases the delivery tip to match the new value.\n    function matchValue(Tips tips, uint256 newValue) internal pure returns (Tips newTips) {\n        uint256 oldValue = tips.value();\n        if (newValue \u003c oldValue) revert TipsValueTooLow();\n        // We want to increase the delivery tip, while keeping the other tips the same\n        unchecked {\n            uint256 delta = (newValue - oldValue) \u003e\u003e TIPS_GRANULARITY;\n            // `delta` fits into uint224, as TIPS_GRANULARITY is 32, so this never overflows uint256.\n            // In practice, this will never overflow uint64 as well, but we still check it just in case.\n            if (delta + tips.deliveryTip() \u003e type(uint64).max) revert TipsOverflow();\n            // Delivery tips occupy lowest 8 bytes, so we can just add delta to the tips value\n            // to effectively increase the delivery tip (knowing that delta fits into uint64).\n            newTips = Tips.wrap(Tips.unwrap(tips) + delta);\n        }\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    function __Ownable_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable_init_unchained() internal onlyInitializing {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n    function __Ownable2Step_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable2Step_init_unchained() internal onlyInitializing {\n    }\n    address private _pendingOwner;\n\n    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Returns the address of the pending owner.\n     */\n    function pendingOwner() public view virtual returns (address) {\n        return _pendingOwner;\n    }\n\n    /**\n     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual override onlyOwner {\n        _pendingOwner = newOwner;\n        emit OwnershipTransferStarted(owner(), newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual override {\n        delete _pendingOwner;\n        super._transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev The new owner accepts the ownership transfer.\n     */\n    function acceptOwnership() public virtual {\n        address sender = _msgSender();\n        require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n        _transferOwnership(sender);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// contracts/libs/memory/State.sol\n\n/// State is a memory view over a formatted state payload.\ntype State is uint256;\n\nusing StateLib for State global;\n\n/// # State\n/// State structure represents the state of Origin contract at some point of time.\n/// - State is structured in a way to track the updates of the Origin Merkle Tree.\n/// - State includes root of the Origin Merkle Tree, origin domain and some additional metadata.\n/// ## Origin Merkle Tree\n/// Hash of every sent message is inserted in the Origin Merkle Tree, which changes\n/// the value of Origin Merkle Root (which is the root for the mentioned tree).\n/// - Origin has a single Merkle Tree for all messages, regardless of their destination domain.\n/// - This leads to Origin state being updated if and only if a message was sent in a block.\n/// - Origin contract is a \"source of truth\" for states: a state is considered \"valid\" in its Origin,\n/// if it matches the state of the Origin contract after the N-th (nonce) message was sent.\n///\n/// # Memory layout of State fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                    |\n/// | ---------- | ----------- | ------- | ----- | ------------------------------ |\n/// | [000..032) | root        | bytes32 | 32    | Root of the Origin Merkle Tree |\n/// | [032..036) | origin      | uint32  | 4     | Domain where Origin is located |\n/// | [036..040) | nonce       | uint32  | 4     | Amount of sent messages        |\n/// | [040..045) | blockNumber | uint40  | 5     | Block of last sent message     |\n/// | [045..050) | timestamp   | uint40  | 5     | Time of last sent message      |\n/// | [050..062) | gasData     | uint96  | 12    | Gas data for the chain         |\n///\n/// @dev State could be used to form a Snapshot to be signed by a Guard or a Notary.\nlibrary StateLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_ROOT = 0;\n    uint256 private constant OFFSET_ORIGIN = 32;\n    uint256 private constant OFFSET_NONCE = 36;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 40;\n    uint256 private constant OFFSET_TIMESTAMP = 45;\n    uint256 private constant OFFSET_GAS_DATA = 50;\n\n    // ═══════════════════════════════════════════════════ STATE ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted State payload with provided fields\n     * @param root_         New merkle root\n     * @param origin_       Domain of Origin's chain\n     * @param nonce_        Nonce of the merkle root\n     * @param blockNumber_  Block number when root was saved in Origin\n     * @param timestamp_    Block timestamp when root was saved in Origin\n     * @param gasData_      Gas data for the chain\n     * @return Formatted state\n     */\n    function formatState(\n        bytes32 root_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_,\n        GasData gasData_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(root_, origin_, nonce_, blockNumber_, timestamp_, gasData_);\n    }\n\n    /**\n     * @notice Returns a State view over the given payload.\n     * @dev Will revert if the payload is not a state.\n     */\n    function castToState(bytes memory payload) internal pure returns (State) {\n        return castToState(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a State view.\n     * @dev Will revert if the memory view is not over a state.\n     */\n    function castToState(MemView memView) internal pure returns (State) {\n        if (!isState(memView)) revert UnformattedState();\n        return State.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted State.\n    function isState(MemView memView) internal pure returns (bool) {\n        return memView.len() == STATE_LENGTH;\n    }\n\n    /// @notice Returns the hash of a State, that could be later signed by a Guard to signal\n    /// that the state is invalid.\n    function hashInvalid(State state) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(stateInvalidSalt, keccak(state))\n        return state.unwrap().keccakSalted(STATE_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(State state) internal pure returns (MemView) {\n        return MemView.wrap(State.unwrap(state));\n    }\n\n    /// @notice Compares two State structures.\n    function equals(State a, State b) internal pure returns (bool) {\n        // Length of a State payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═══════════════════════════════════════════════ STATE HASHING ═══════════════════════════════════════════════════\n\n    /// @notice Returns the hash of the State.\n    /// @dev We are using the Merkle Root of a tree with two leafs (see below) as state hash.\n    function leaf(State state) internal pure returns (bytes32) {\n        (bytes32 leftLeaf_, bytes32 rightLeaf_) = state.subLeafs();\n        // Final hash is the parent of these leafs\n        return keccak256(bytes.concat(leftLeaf_, rightLeaf_));\n    }\n\n    /// @notice Returns \"sub-leafs\" of the State. Hash of these \"sub leafs\" is going to be used\n    /// as a \"state leaf\" in the \"Snapshot Merkle Tree\".\n    /// This enables proving that leftLeaf = (root, origin) was a part of the \"Snapshot Merkle Tree\",\n    /// by combining `rightLeaf` with the remainder of the \"Snapshot Merkle Proof\".\n    function subLeafs(State state) internal pure returns (bytes32 leftLeaf_, bytes32 rightLeaf_) {\n        MemView memView = state.unwrap();\n        // Left leaf is (root, origin)\n        leftLeaf_ = memView.prefix({len_: OFFSET_NONCE}).keccak();\n        // Right leaf is (metadata), or (nonce, blockNumber, timestamp)\n        rightLeaf_ = memView.sliceFrom({index_: OFFSET_NONCE}).keccak();\n    }\n\n    /// @notice Returns the left \"sub-leaf\" of the State.\n    function leftLeaf(bytes32 root_, uint32 origin_) internal pure returns (bytes32) {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(root_, origin_));\n    }\n\n    /// @notice Returns the right \"sub-leaf\" of the State.\n    function rightLeaf(uint32 nonce_, uint40 blockNumber_, uint40 timestamp_, GasData gasData_)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(nonce_, blockNumber_, timestamp_, gasData_));\n    }\n\n    // ═══════════════════════════════════════════════ STATE SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns a historical Merkle root from the Origin contract.\n    function root(State state) internal pure returns (bytes32) {\n        return state.unwrap().index({index_: OFFSET_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns domain of chain where the Origin contract is deployed.\n    function origin(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns nonce of Origin contract at the time, when `root` was the Merkle root.\n    function nonce(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when `root` was saved in Origin.\n    function blockNumber(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when `root` was saved in Origin.\n    /// @dev This is the timestamp according to the origin chain.\n    function timestamp(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n\n    /// @notice Returns gas data for the chain.\n    function gasData(State state) internal pure returns (GasData) {\n        return GasDataLib.wrapGasData(state.unwrap().indexUint({index_: OFFSET_GAS_DATA, bytes_: GAS_DATA_LENGTH}));\n    }\n}\n\n// contracts/libs/memory/BaseMessage.sol\n\n/// BaseMessage is a memory view over the base message supported by Origin-Destination\ntype BaseMessage is uint256;\n\nusing BaseMessageLib for BaseMessage global;\n\n/// BaseMessage structure represents a base message sent via the Origin-Destination contracts.\n/// - It only contains data relevant to the base message, the rest of data is encoded in the message header.\n/// - `sender` and `recipient` for EVM chains are EVM addresses casted to bytes32, while preserving left-alignment.\n/// - `tips` and `request` parameters are specified by a message sender\n/// \u003e Origin will calculate minimum tips for given request and content length, and will reject messages with tips\n/// lower than that.\n///\n/// # Memory layout of BaseMessage fields\n///\n/// | Position   | Field     | Type    | Bytes | Description                            |\n/// | ---------- | --------- | ------- | ----- | -------------------------------------- |\n/// | [000..032) | tips      | uint256 | 32    | Encoded tips paid on origin chain      |\n/// | [032..064) | sender    | bytes32 | 32    | Sender address on origin chain         |\n/// | [064..096) | recipient | bytes32 | 32    | Recipient address on destination chain |\n/// | [096..116) | request   | uint160 | 20    | Encoded request for message execution  |\n/// | [104..AAA) | content   | bytes   | ??    | Content to be passed to recipient      |\nlibrary BaseMessageLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_TIPS = 0;\n    uint256 private constant OFFSET_SENDER = 32;\n    uint256 private constant OFFSET_RECIPIENT = 64;\n    uint256 private constant OFFSET_REQUEST = OFFSET_RECIPIENT + TIPS_LENGTH;\n    uint256 private constant OFFSET_CONTENT = OFFSET_REQUEST + REQUEST_LENGTH;\n\n    // ═══════════════════════════════════════════════ BASE MESSAGE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted BaseMessage payload with provided fields.\n     * @param tips_         Encoded tips information\n     * @param sender_       Sender address on origin chain\n     * @param recipient_    Recipient address on destination chain\n     * @param request_      Encoded request for message execution\n     * @param content_      Raw content to be passed to recipient on destination chain\n     * @return Formatted base message\n     */\n    function formatBaseMessage(Tips tips_, bytes32 sender_, bytes32 recipient_, Request request_, bytes memory content_)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return abi.encodePacked(tips_, sender_, recipient_, request_, content_);\n    }\n\n    /**\n     * @notice Returns a BaseMessage view over the given payload.\n     * @dev Will revert if the payload is not a base message.\n     */\n    function castToBaseMessage(bytes memory payload) internal pure returns (BaseMessage) {\n        return castToBaseMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a BaseMessage view.\n     * @dev Will revert if the memory view is not over a base message payload.\n     */\n    function castToBaseMessage(MemView memView) internal pure returns (BaseMessage) {\n        if (!isBaseMessage(memView)) revert UnformattedBaseMessage();\n        return BaseMessage.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted BaseMessage.\n    function isBaseMessage(MemView memView) internal pure returns (bool) {\n        // Check if sender, recipient, tips fields exist\n        return (memView.len() \u003e= OFFSET_CONTENT);\n        // Content could be empty, so we don't check that\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(BaseMessage baseMessage) internal pure returns (MemView) {\n        return MemView.wrap(BaseMessage.unwrap(baseMessage));\n    }\n\n    /// @notice Returns baseMessage's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        // We hash \"tips\" and \"everything but tips\" to make tips proofs easier to verify\n        return MerkleMath.getParent(baseMessage.tips().leaf(), baseMessage.bodyLeaf());\n    }\n\n    /// @notice Returns hash for the \"everything but tips\" part of the base message.\n    function bodyLeaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_SENDER}).keccak();\n    }\n\n    // ═══════════════════════════════════════════ BASE MESSAGE SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips paid on origin chain.\n    function tips(BaseMessage baseMessage) internal pure returns (Tips) {\n        return TipsLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_TIPS, bytes_: TIPS_LENGTH})));\n    }\n\n    /// @notice Returns sender address on origin chain.\n    function sender(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_SENDER, bytes_: 32});\n    }\n\n    /// @notice Returns recipient address on destination chain.\n    function recipient(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_RECIPIENT, bytes_: 32});\n    }\n\n    /// @notice Returns an encoded request for message execution on destination chain.\n    function request(BaseMessage baseMessage) internal pure returns (Request) {\n        return RequestLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_REQUEST, bytes_: REQUEST_LENGTH})));\n    }\n\n    /// @notice Returns an untyped memory view over the content to be passed to recipient.\n    function content(BaseMessage baseMessage) internal pure returns (MemView) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_CONTENT});\n    }\n}\n\n// contracts/base/MessagingBase.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for all messaging contracts.\n * - Provides context on the local chain's domain.\n * - Provides ownership functionality.\n * - Will be providing pausing functionality when it is implemented.\n */\nabstract contract MessagingBase is MultiCallable, Versioned, Ownable2StepUpgradeable {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @notice Domain of the local chain, set once upon contract creation\n    uint32 public immutable localDomain;\n    // @notice Domain of the Synapse chain, set once upon contract creation\n    uint32 public immutable synapseDomain;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev gap for upgrade safety\n    uint256[50] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    constructor(string memory version_, uint32 synapseDomain_) Versioned(version_) {\n        localDomain = ChainContext.chainId();\n        synapseDomain = synapseDomain_;\n    }\n\n    // TODO: Implement pausing\n\n    /**\n     * @dev Should be impossible to renounce ownership;\n     * we override OpenZeppelin OwnableUpgradeable's\n     * implementation of renounceOwnership to make it a no-op\n     */\n    function renounceOwnership() public override onlyOwner {} //solhint-disable-line no-empty-blocks\n}\n\n// contracts/libs/memory/Message.sol\n\n/// Message is a memory over over a formatted message payload.\ntype Message is uint256;\n\nusing MessageLib for Message global;\n\n/// Library for formatting the various messages supported by Origin and Destination.\n///\n/// # Message memory layout\n///\n/// | Position   | Field  | Type    | Bytes | Description                                             |\n/// | ---------- | ------ | ------- | ----- | ------------------------------------------------------- |\n/// | [000..017) | header | uint136 | 17    | Encoded general routing information for the message     |\n/// | [017..AAA) | body   | bytes   | ??    | Formatted payload (according to flag) with message body |\nlibrary MessageLib {\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MemViewLib for bytes;\n    using HeaderLib for MemView;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_HEADER = 0;\n    uint256 private constant OFFSET_BODY = OFFSET_HEADER + HEADER_LENGTH;\n\n    // ══════════════════════════════════════════════════ MESSAGE ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns formatted message with provided fields.\n     * @param header_   Encoded general routing information for the message\n     * @param body_     Formatted payload (according to flag) with message body\n     * @return Formatted message\n     */\n    function formatMessage(Header header_, bytes memory body_) internal pure returns (bytes memory) {\n        return abi.encodePacked(header_, body_);\n    }\n\n    /**\n     * @notice Returns a Message view over for the given payload.\n     * @dev Will revert if the payload is not a message payload.\n     */\n    function castToMessage(bytes memory payload) internal pure returns (Message) {\n        return castToMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Message view.\n     * @dev Will revert if the memory view is not over a message payload.\n     */\n    function castToMessage(MemView memView) internal pure returns (Message) {\n        if (!isMessage(memView)) revert UnformattedMessage();\n        return Message.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Message.\n     */\n    function isMessage(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Check if headers exist in the payload\n        if (length \u003c OFFSET_BODY) return false;\n        // Check that Header is valid\n        uint256 paddedHeader = _header(memView);\n        if (!HeaderLib.isHeader(paddedHeader)) return false;\n        // Check that body is formatted according to the flag\n        // Only Base/Manager message flags exist\n        if (HeaderLib.wrapPadded(paddedHeader).flag() == MessageFlag.Base) {\n            // Check if body is a formatted base message\n            return _body(memView).isBaseMessage();\n        } else {\n            // Check if body is a formatted calldata for AgentManager call\n            return _body(memView).isCallData();\n        }\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Message message) internal pure returns (MemView) {\n        return MemView.wrap(Message.unwrap(message));\n    }\n\n    /// @notice Returns message's hash: a leaf to be inserted in the Merkle tree.\n    function leaf(Message message) internal pure returns (bytes32) {\n        // We hash header and body separately to make message proofs easier to verify\n        Header header_ = message.header();\n        // Only Base/Manager message flags exist\n        if (header_.flag() == MessageFlag.Base) {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToBaseMessage().leaf());\n        } else {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToCallData().leaf());\n        }\n    }\n\n    // ══════════════════════════════════════════════ MESSAGE SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns message's encoded header field.\n    function header(Message message) internal pure returns (Header) {\n        return HeaderLib.wrapPadded((message.unwrap().indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH})));\n    }\n\n    /// @notice Returns message's body field as an untyped memory view.\n    function body(Message message) internal pure returns (MemView) {\n        MemView memView = message.unwrap();\n        return _body(memView);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns message's padded header without checking that it is a valid header.\n    function _header(MemView memView) private pure returns (uint256) {\n        return memView.indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH});\n    }\n\n    /// @dev Returns an untyped memory view over the body field without checking\n    /// if the whole payload or the body are properly formatted.\n    function _body(MemView memView) private pure returns (MemView) {\n        return memView.sliceFrom({index_: OFFSET_BODY});\n    }\n}\n\n// contracts/base/AgentSecured.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for messaging contracts that are secured by the agent manager.\n * `AgentSecured` relies on `AgentManager` to provide the following functionality:\n * - Keep track of agents and their statuses.\n * - Pass agent-signed statements that were verified by the agent manager.\n * - These statements are considered valid indefinitely, unless the agent is disputed.\n * - Disputes are opened and resolved by the agent manager.\n * \u003e `AgentSecured` implementation should never use statements signed by agents that are disputed.\n */\nabstract contract AgentSecured is MessagingBase, IAgentSecured {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    address public immutable agentManager;\n\n    /// @inheritdoc IAgentSecured\n    address public immutable inbox;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    // (agent index =\u003e their dispute status: flag, openedAt, resolvedAt)\n    mapping(uint32 =\u003e DisputeStatus) internal _disputes;\n\n    /// @dev gap for upgrade safety\n    uint256[49] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    modifier onlyAgentManager() {\n        if (msg.sender != agentManager) revert CallerNotAgentManager();\n        _;\n    }\n\n    modifier onlyInbox() {\n        if (msg.sender != inbox) revert CallerNotInbox();\n        _;\n    }\n\n    constructor(string memory version_, uint32 synapseDomain_, address agentManager_, address inbox_)\n        MessagingBase(version_, synapseDomain_)\n    {\n        agentManager = agentManager_;\n        inbox = inbox_;\n    }\n\n    // ════════════════════════════════════════════ ONLY AGENT MANAGER ═════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external onlyAgentManager {\n        uint40 openedAt = ChainContext.blockTimestamp();\n        DisputeStatus memory status = DisputeStatus({flag: DisputeFlag.Pending, openedAt: openedAt, resolvedAt: 0});\n        _disputes[guardIndex] = status;\n        _disputes[notaryIndex] = status;\n    }\n\n    /// @inheritdoc IAgentSecured\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external onlyAgentManager {\n        // Update the dispute status of the slashed agent first.\n        uint40 resolvedAt = ChainContext.blockTimestamp();\n        _disputes[slashedIndex].flag = DisputeFlag.Slashed;\n        _disputes[slashedIndex].resolvedAt = resolvedAt;\n        // Mark the rival agent as not disputed, if there was an ongoing dispute.\n        if (rivalIndex != 0) {\n            _disputes[rivalIndex].flag = DisputeFlag.None;\n            _disputes[rivalIndex].resolvedAt = resolvedAt;\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function agentStatus(address agent) external view returns (AgentStatus memory) {\n        return _agentStatus(agent);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status) {\n        return _getAgent(index);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory) {\n        return _disputes[agentIndex];\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns status of the given agent: (flag, domain, index).\n    function _agentStatus(address agent) internal view returns (AgentStatus memory) {\n        return IAgentManager(agentManager).agentStatus(agent);\n    }\n\n    /// @dev Returns agent and their status for a given agent index. Returns zero values for non existing indexes.\n    function _getAgent(uint256 index) internal view returns (address agent, AgentStatus memory status) {\n        return IAgentManager(agentManager).getAgent(index);\n    }\n\n    /// @dev Checks if a Dispute exists for the given Notary. This function returns true, if\n    /// Notary is in ongoing Dispute, or if Dispute was resolved not in Notary's favor.\n    /// In both cases we can't trust Notary's data.\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeExists(uint32 notaryIndex) internal view returns (bool) {\n        return _disputes[notaryIndex].flag != DisputeFlag.None;\n    }\n\n    /// @dev Checks if a Notary recently won a Dispute and is still in the \"post-dispute\" timeout period.\n    /// In this period we still can't trust Notary's data, though we can optimistically assume that\n    /// that the data will be correct after the timeout (assuming no new Disputes are opened).\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeTimeout(uint32 notaryIndex) internal view returns (bool) {\n        DisputeStatus memory status = _disputes[notaryIndex];\n        // Exit early if Notary is in ongoing Dispute / slashed.\n        if (status.flag != DisputeFlag.None) return false;\n        // Check if Notary has been in any Dispute at all.\n        if (status.openedAt == 0) return false;\n        // Otherwise check if the Dispute timeout is still active.\n        return block.timestamp \u003c status.resolvedAt + DISPUTE_TIMEOUT_NOTARY;\n    }\n}\n\n// contracts/hubs/StateHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StateHub` is a parent contract for `Origin`. It is responsible for the following:\n/// - Keeping track of the historical Origin Merkle Tree containing all the message hashes.\n/// - Keeping track of the historical Origin States, as well as verifying their validity.\nabstract contract StateHub is AgentSecured, StateHubEvents, IStateHub {\n    using SafeCast for uint256;\n    using StateLib for bytes;\n\n    struct OriginState {\n        uint40 blockNumber;\n        uint40 timestamp;\n        GasData gasData;\n    }\n    // Bits left for tight packing: 80\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Historical Merkle Tree\n    /// Note: Takes two storage slots\n    HistoricalTree private _tree;\n\n    /// @dev All historical contract States\n    OriginState[] private _originStates;\n\n    /// @dev gap for upgrade safety\n    uint256[47] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IStateHub\n    function isValidState(bytes memory statePayload) external view returns (bool isValid) {\n        // This will revert if payload is not a formatted state\n        State state = statePayload.castToState();\n        return _isValidState(state);\n    }\n\n    /// @inheritdoc IStateHub\n    function statesAmount() external view returns (uint256) {\n        return _originStates.length;\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestLatestState() external view returns (bytes memory stateData) {\n        // This never underflows, assuming the contract was initialized\n        return suggestState(_nextNonce() - 1);\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestState(uint32 nonce) public view returns (bytes memory stateData) {\n        // This will revert if nonce is out of range\n        bytes32 root = _tree.root(nonce);\n        return _formatOriginState(_originStates[nonce], root, localDomain, nonce);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Initializes the saved states list by inserting a state for an empty Merkle Tree.\n    function _initializeStates() internal {\n        // This should only be called once, when the contract is initialized\n        // This will revert if _tree.roots is non-empty\n        bytes32 savedRoot = _tree.initializeRoots();\n        // Save root for empty merkle _tree with block number and timestamp of initialization\n        _saveState(savedRoot, _toOriginState());\n    }\n\n    /// @dev Inserts leaf into the Merkle Tree and saves the updated origin State.\n    function _insertAndSave(bytes32 leaf) internal {\n        bytes32 newRoot = _tree.insert(leaf);\n        _saveState(newRoot, _toOriginState());\n    }\n\n    /// @dev Saves an updated state of the Origin contract\n    function _saveState(bytes32 root, OriginState memory state) internal {\n        uint32 nonce = _nextNonce();\n        _originStates.push(state);\n        // Emit event with raw state data\n        emit StateSaved(_formatOriginState(state, root, localDomain, nonce));\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns nonce of the next sent message: the amount of saved States so far.\n    /// This always equals to \"total amount of sent messages\" plus 1.\n    function _nextNonce() internal view returns (uint32) {\n        // TODO: consider using more than 32 bits for origin nonces\n        return _originStates.length.toUint32();\n    }\n\n    /// @dev Checks if a state is valid, i.e. if it matches the historical one.\n    /// Reverts, if state refers to another Origin contract.\n    function _isValidState(State state) internal view returns (bool) {\n        // Check if state refers to this contract\n        if (state.origin() != localDomain) revert IncorrectOriginDomain();\n        // Check if nonce exists\n        uint32 nonce = state.nonce();\n        if (nonce \u003e= _originStates.length) return false;\n        // Check if state root matches the historical one\n        if (state.root() != _tree.root(nonce)) return false;\n        // Check if state metadata matches the historical one\n        return _areEqual(state, _originStates[nonce]);\n    }\n\n    // ═════════════════════════════════════════════ STRUCT FORMATTING ═════════════════════════════════════════════════\n\n    /// @dev Returns a formatted payload for a stored OriginState.\n    function _formatOriginState(OriginState memory originState, bytes32 root, uint32 origin, uint32 nonce)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return StateLib.formatState({\n            root_: root,\n            origin_: origin,\n            nonce_: nonce,\n            blockNumber_: originState.blockNumber,\n            timestamp_: originState.timestamp,\n            gasData_: originState.gasData\n        });\n    }\n\n    /// @dev Child contract should implement the logic for getting the current gas data from the gas oracle\n    /// to be saved as part of the Origin State.\n    // solhint-disable-next-line ordering\n    function _fetchGasData() internal view virtual returns (GasData);\n\n    /// @dev Returns a OriginState struct to save in the contract.\n    function _toOriginState() internal view returns (OriginState memory originState) {\n        originState.blockNumber = ChainContext.blockNumber();\n        originState.timestamp = ChainContext.blockTimestamp();\n        originState.gasData = _fetchGasData();\n    }\n\n    /// @dev Checks that a state and its Origin representation are equal.\n    function _areEqual(State state, OriginState memory originState) internal pure returns (bool) {\n        return state.blockNumber() == originState.blockNumber \u0026\u0026 state.timestamp() == originState.timestamp;\n    }\n}\n\n// contracts/Origin.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Origin` contract is used for sending messages to remote chains. It is done\n/// by inserting the message hashes into the Origin Merkle, which makes it possible to\n/// prove that message was sent using the Merkle proof against the Origin Merkle Root. This essentially\n/// compresses the list of messages into a single 32-byte value that needs to be stored on the destination chain.\n/// `Origin` is responsible for the following:\n/// - Formatting the sent message payloads, and inserting their hashes into the Origin Merkle Tree.\n/// - Keeping track of its own historical states (see parent contract `StateHub`).\n/// - Enforcing minimum tip values for sent base messages based on the provided execution requests.\n/// - Distributing the collected tips upon request from a local `AgentManager` contract.\ncontract Origin is StateHub, OriginEvents, InterfaceOrigin {\n    using MemViewLib for bytes;\n    using MessageLib for bytes;\n    using TipsLib for bytes;\n    using TypeCasts for address;\n\n    address public immutable gasOracle;\n\n    modifier onlyRemoteDestination(uint32 destination) {\n        if (destination == localDomain) revert IncorrectDestinationDomain();\n        _;\n    }\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_, address gasOracle_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {\n        gasOracle = gasOracle_;\n    }\n\n    /// @notice Initializes Origin contract:\n    /// - msg.sender is set as contract owner\n    /// - State of \"empty merkle tree\" is saved\n    function initialize() external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize \"states\": state of an \"empty merkle tree\" is saved\n        _initializeStates();\n    }\n\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable onlyRemoteDestination(destination) returns (uint32 messageNonce, bytes32 messageHash) {\n        // Check that content is not too large\n        if (content.length \u003e MAX_CONTENT_BYTES) revert ContentLengthTooBig();\n        // This will revert if msg.value is lower than value of minimum tips\n        Tips tips = _getMinimumTips(destination, paddedRequest, content.length).matchValue(msg.value);\n        Request request = RequestLib.wrapPadded(paddedRequest);\n        // Format the BaseMessage body\n        bytes memory body = BaseMessageLib.formatBaseMessage({\n            sender_: msg.sender.addressToBytes32(),\n            recipient_: recipient,\n            tips_: tips,\n            request_: request,\n            content_: content\n        });\n        // Send the message\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Base, body);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        onlyAgentManager\n        onlyRemoteDestination(destination)\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // AgentManager (checked via modifier) is responsible for constructing the calldata payload correctly.\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Manager, payload);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function withdrawTips(address recipient, uint256 amount) external onlyAgentManager {\n        if (address(this).balance \u003c amount) revert InsufficientEthBalance();\n        (bool success,) = recipient.call{value: amount}(\"\");\n        if (!success) revert EthTransferFailed();\n        emit TipWithdrawalCompleted(recipient, amount);\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue)\n    {\n        return _getMinimumTips(destination, paddedRequest, contentLength).value();\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Sends the given message to the specified destination. Message hash is inserted\n    /// into the Origin Merkle Tree, which will enable message execution on destination chain.\n    function _sendMessage(uint32 destination, uint32 optimisticPeriod, MessageFlag flag, bytes memory body)\n        internal\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // Format the message header\n        messageNonce = _nextNonce();\n        Header header = flag.encodeHeader({\n            origin_: localDomain,\n            nonce_: messageNonce,\n            destination_: destination,\n            optimisticPeriod_: optimisticPeriod\n        });\n        // Format the full message payload\n        bytes memory msgPayload = MessageLib.formatMessage(header, body);\n        // Insert new leaf into the Origin Merkle Tree and save the updated state\n        messageHash = msgPayload.castToMessage().leaf();\n        _insertAndSave(messageHash);\n        // Emit event with message information\n        emit Sent(messageHash, messageNonce, destination, msgPayload);\n        // Update the gas oracle data. We do this after the provided tips are checked so that\n        // the provided message is sent in the event that the gas oracle data is updated to a higher value.\n        InterfaceGasOracle(gasOracle).updateGasData(destination);\n        // TODO: consider doing this before the message is sent, while adjusting GasOracle.getMinimumTips() to\n        // use the pending gas oracle data.\n    }\n\n    /// @dev Returns the minimum tips for sending a message to the given destination with the given request and content.\n    function _getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        internal\n        view\n        returns (Tips)\n    {\n        return\n            TipsLib.wrapPadded(InterfaceGasOracle(gasOracle).getMinimumTips(destination, paddedRequest, contentLength));\n    }\n\n    /// @dev Gets the current gas data from the gas oracle to be saved as part of the Origin State.\n    function _fetchGasData() internal view override returns (GasData) {\n        return GasDataLib.wrapGasData(InterfaceGasOracle(gasOracle).getGasData());\n    }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"114748:7222:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;114748:7222:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"114748:7222:0:-:0;;;;;;;;","abiDefinition":[],"userDoc":{"kind":"user","methods":{},"notice":"Library for encoding and decoding GasData and ChainGas structs. # GasData `GasData` is a struct to store the \"basic information about gas prices\", that could be later used to approximate the cost of a message execution, and thus derive the minimal tip values for sending a message to the chain. \u003e - `GasData` is supposed to be cached by `GasOracle` contract, allowing to store the \u003e approximates instead of the exact values, and thus save on storage costs. \u003e - For instance, if `GasOracle` only updates the values on +- 10% change, having an \u003e 0.4% error on the approximates would be acceptable. `GasData` is supposed to be included in the Origin's state, which are synced across chains using Agent-signed snapshots and attestations. ## GasData stack layout (from highest bits to lowest) | Position   | Field        | Type   | Bytes | Description                                         | | ---------- | ------------ | ------ | ----- | --------------------------------------------------- | | (012..010] | gasPrice     | uint16 | 2     | Gas price for the chain (in Wei per gas unit)       | | (010..008] | dataPrice    | uint16 | 2     | Calldata price (in Wei per byte of content)         | | (008..006] | execBuffer   | uint16 | 2     | Tx fee safety buffer for message execution (in Wei) | | (006..004] | amortAttCost | uint16 | 2     | Amortized cost for attestation submission (in Wei)  | | (004..002] | etherPrice   | uint16 | 2     | Chain's Ether Price / Mainnet Ether Price (in BWAD) | | (002..000] | markup       | uint16 | 2     | Markup for the message execution (in BWAD)          | \u003e See Number.sol for more details on `Number` type and BWAD (binary WAD) math. ## ChainGas stack layout (from highest bits to lowest) | Position   | Field   | Type   | Bytes | Description      | | ---------- | ------- | ------ | ----- | ---------------- | | (016..004] | gasData | uint96 | 12    | Chain's gas data | | (004..000] | domain  | uint32 | 4     | Chain's domain   |","version":1},"developerDoc":{"kind":"dev","methods":{},"stateVariables":{"SHIFT_AMORT_ATT_COST":{"details":"Amount of bits to shift to amortAttCost field"},"SHIFT_DATA_PRICE":{"details":"Amount of bits to shift to dataPrice field"},"SHIFT_ETHER_PRICE":{"details":"Amount of bits to shift to etherPrice field"},"SHIFT_EXEC_BUFFER":{"details":"Amount of bits to shift to execBuffer field"},"SHIFT_GAS_DATA":{"details":"Amount of bits to shift to gasData field"},"SHIFT_GAS_PRICE":{"details":"Amount of bits to shift to gasPrice field"}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"stateVariables\":{\"SHIFT_AMORT_ATT_COST\":{\"details\":\"Amount of bits to shift to amortAttCost field\"},\"SHIFT_DATA_PRICE\":{\"details\":\"Amount of bits to shift to dataPrice field\"},\"SHIFT_ETHER_PRICE\":{\"details\":\"Amount of bits to shift to etherPrice field\"},\"SHIFT_EXEC_BUFFER\":{\"details\":\"Amount of bits to shift to execBuffer field\"},\"SHIFT_GAS_DATA\":{\"details\":\"Amount of bits to shift to gasData field\"},\"SHIFT_GAS_PRICE\":{\"details\":\"Amount of bits to shift to gasPrice field\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"Library for encoding and decoding GasData and ChainGas structs. # GasData `GasData` is a struct to store the \\\"basic information about gas prices\\\", that could be later used to approximate the cost of a message execution, and thus derive the minimal tip values for sending a message to the chain. \u003e - `GasData` is supposed to be cached by `GasOracle` contract, allowing to store the \u003e approximates instead of the exact values, and thus save on storage costs. \u003e - For instance, if `GasOracle` only updates the values on +- 10% change, having an \u003e 0.4% error on the approximates would be acceptable. `GasData` is supposed to be included in the Origin's state, which are synced across chains using Agent-signed snapshots and attestations. ## GasData stack layout (from highest bits to lowest) | Position   | Field        | Type   | Bytes | Description                                         | | ---------- | ------------ | ------ | ----- | --------------------------------------------------- | | (012..010] | gasPrice     | uint16 | 2     | Gas price for the chain (in Wei per gas unit)       | | (010..008] | dataPrice    | uint16 | 2     | Calldata price (in Wei per byte of content)         | | (008..006] | execBuffer   | uint16 | 2     | Tx fee safety buffer for message execution (in Wei) | | (006..004] | amortAttCost | uint16 | 2     | Amortized cost for attestation submission (in Wei)  | | (004..002] | etherPrice   | uint16 | 2     | Chain's Ether Price / Mainnet Ether Price (in BWAD) | | (002..000] | markup       | uint16 | 2     | Markup for the message execution (in BWAD)          | \u003e See Number.sol for more details on `Number` type and BWAD (binary WAD) math. ## ChainGas stack layout (from highest bits to lowest) | Position   | Field   | Type   | Bytes | Description      | | ---------- | ------- | ------ | ----- | ---------------- | | (016..004] | gasData | uint96 | 12    | Chain's gas data | | (004..000] | domain  | uint32 | 4     | Chain's domain   |\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Origin.sol\":\"GasDataLib\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Origin.sol\":{\"keccak256\":\"0x96775924f147f3d1f8df8cdf56731fe52a15af8d8e12e608efb8158c112b18cd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e642a27f5fab3c62b4c02e9754e9e42b1cf2e5381dbea9d3d106d23b7772ebe6\",\"dweb:/ipfs/QmUwn7ZyBvPkjnMuK8ZMSexBUdNQnVtxwyoAyT4DXLQjra\"]}},\"version\":1}"},"hashes":{}},"solidity/Origin.sol:HeaderLib":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212202f3c31e84bf22190a6777a10e95c26efc16df477ae3565c44a16a4722814363764736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212202f3c31e84bf22190a6777a10e95c26efc16df477ae3565c44a16a4722814363764736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/OriginEvents.sol\n\n/// @notice A collection of events emitted by the Origin contract\nabstract contract OriginEvents {\n    /**\n     * @notice Emitted when a new message is sent.\n     * @param messageHash   Hash of message; the leaf inserted to the Merkle tree for the message\n     * @param nonce         Nonce of sent message (starts from 1)\n     * @param destination   Destination domain\n     * @param message       Raw bytes of message\n     */\n    event Sent(bytes32 indexed messageHash, uint32 indexed nonce, uint32 indexed destination, bytes message);\n\n    /**\n     * @notice Emitted when a tip withdrawal is completed.\n     * @param actor     Actor address\n     * @param tip       Tip value, denominated in local domain's wei\n     */\n    event TipWithdrawalCompleted(address actor, uint256 tip);\n}\n\n// contracts/events/StateHubEvents.sol\n\n/// @notice A collection of events emitted by the StateHub contract\nabstract contract StateHubEvents {\n    /**\n     * @notice Emitted when a new Origin State is saved after a message was sent.\n     * @param state     Raw payload with state data\n     */\n    event StateSaved(bytes state);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n    /**\n     * @notice Check that a given state is valid: matches the historical state of Origin contract.\n     * Note: any Agent including an invalid state in their snapshot will be slashed\n     * upon providing the snapshot and agent signature for it to Origin contract.\n     * @dev Will revert if any of these is true:\n     *  - State payload is not properly formatted.\n     * @param statePayload      Raw payload with state data\n     * @return isValid          Whether the provided state is valid\n     */\n    function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns the amount of saved states so far.\n     * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n     */\n    function statesAmount() external view returns (uint256);\n\n    /**\n     * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @return statePayload     Raw payload with the latest state data\n     */\n    function suggestLatestState() external view returns (bytes memory statePayload);\n\n    /**\n     * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @param nonce             Historical nonce to form a state\n     * @return statePayload     Raw payload with historical state data\n     */\n    function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/InterfaceGasOracle.sol\n\ninterface InterfaceGasOracle {\n    /**\n     * @notice Fetches the latest gas data for the chain from `Destination` contract,\n     * and uses it to update the oracle values for the requested chain.\n     * @param domain    Domain to update the gas data for\n     */\n    function updateGasData(uint32 domain) external;\n\n    /**\n     * @notice Returns the gas data for the local chain.\n     */\n    function getGasData() external view returns (uint256 paddedGasData);\n\n    /**\n     * @notice Returns the gas data for the given domain, in the decoded format.\n     * @param domain        Domain of chain to get gas data for\n     * @return gasPrice     Gas price for the chain (in Wei per gas unit)\n     * @return dataPrice    Calldata price (in Wei per byte of content)\n     * @return execBuffer   Tx fee safety buffer for message execution (in Wei)\n     * @return amortAttCost Amortized cost for attestation submission (in Wei)\n     * @return etherPrice   Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n     * @return markup       Markup for the message execution (in BWAD)\n     */\n    function getDecodedGasData(uint32 domain)\n        external\n        view\n        returns (\n            uint256 gasPrice,\n            uint256 dataPrice,\n            uint256 execBuffer,\n            uint256 amortAttCost,\n            uint256 etherPrice,\n            uint256 markup\n        );\n\n    /**\n     * @notice Returns the minimum tips for sending a message to a given destination.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return paddedTips       Padded encoded minimum tips information\n     */\n    function getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 paddedTips);\n}\n\n// contracts/interfaces/InterfaceOrigin.sol\n\ninterface InterfaceOrigin {\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /**\n     * @notice Send a message to the recipient located on destination domain.\n     * @dev Recipient has to conform to IMessageRecipient interface, otherwise message won't be delivered.\n     * Will revert if any of these is true:\n     * - `destination` is equal to contract's local domain\n     * - `content` length is greater than `MAX_CONTENT_BYTES`\n     * - `msg.value` is lower than value of minimum tips for the given message\n     * @param destination           Domain of destination chain\n     * @param recipient             Address of recipient on destination chain as bytes32\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param paddedRequest         Padded encoded message execution request on destination chain\n     * @param content               Raw bytes content of message\n     * @return messageNonce         Nonce of the sent message\n     * @return messageHash          Hash of the sent message\n     */\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable returns (uint32 messageNonce, bytes32 messageHash);\n\n    /**\n     * @notice Send a manager message to the destination domain.\n     * @dev This could only be called by AgentManager, which takes care of encoding the calldata payload.\n     * Note: (msgOrigin, proofMaturity) security args will be added to payload on the destination chain\n     * so that the AgentManager could verify where the Manager Message came from and how mature is the proof.\n     * Note: function is not payable, as no tips are required for sending a manager message.\n     * Will revert if `destination` is equal to contract's local domain.\n     * @param destination           Domain of destination chain\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param payload               Payload for calling AgentManager on destination chain (with extra security args)\n     */\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        returns (uint32 messageNonce, bytes32 messageHash);\n\n    // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Withdraws locked base message tips to the recipient.\n     * @dev Could only be called by a local AgentManager.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function withdrawTips(address recipient, uint256 amount) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the minimum tips value for sending a message to a given destination.\n     * @dev Using at least `tipsValue` as `msg.value` for `sendBaseMessage()`\n     * will guarantee that the message will be accepted.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return tipsValue        Minimum tips value for a message to be accepted\n     */\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue);\n}\n\n// contracts/libs/Constants.sol\n\n// Here we define common constants to enable their easier reusing later.\n\n// ══════════════════════════════════ MERKLE ═══════════════════════════════════\n/// @dev Height of the Agent Merkle Tree\nuint256 constant AGENT_TREE_HEIGHT = 32;\n/// @dev Height of the Origin Merkle Tree\nuint256 constant ORIGIN_TREE_HEIGHT = 32;\n/// @dev Height of the Snapshot Merkle Tree. Allows up to 64 leafs, e.g. up to 32 states\nuint256 constant SNAPSHOT_TREE_HEIGHT = 6;\n// ══════════════════════════════════ STRUCTS ══════════════════════════════════\n/// @dev See Attestation.sol: (bytes32,bytes32,uint32,uint40,uint40): 32+32+4+5+5\nuint256 constant ATTESTATION_LENGTH = 78;\n/// @dev See GasData.sol: (uint16,uint16,uint16,uint16,uint16,uint16): 2+2+2+2+2+2\nuint256 constant GAS_DATA_LENGTH = 12;\n/// @dev See Receipt.sol: (uint32,uint32,bytes32,bytes32,uint8,address,address,address): 4+4+32+32+1+20+20+20\nuint256 constant RECEIPT_LENGTH = 133;\n/// @dev See State.sol: (bytes32,uint32,uint32,uint40,uint40,GasData): 32+4+4+5+5+len(GasData)\nuint256 constant STATE_LENGTH = 50 + GAS_DATA_LENGTH;\n/// @dev Maximum amount of states in a single snapshot. Each state produces two leafs in the tree\nuint256 constant SNAPSHOT_MAX_STATES = 1 \u003c\u003c (SNAPSHOT_TREE_HEIGHT - 1);\n// ══════════════════════════════════ MESSAGE ══════════════════════════════════\n/// @dev See Header.sol: (uint8,uint32,uint32,uint32,uint32): 1+4+4+4+4\nuint256 constant HEADER_LENGTH = 17;\n/// @dev See Request.sol: (uint96,uint64,uint32): 12+8+4\nuint256 constant REQUEST_LENGTH = 24;\n/// @dev See Tips.sol: (uint64,uint64,uint64,uint64): 8+8+8+8\nuint256 constant TIPS_LENGTH = 32;\n/// @dev The amount of discarded last bits when encoding tip values\nuint256 constant TIPS_GRANULARITY = 32;\n/// @dev Tip values could be only the multiples of TIPS_MULTIPLIER\nuint256 constant TIPS_MULTIPLIER = 1 \u003c\u003c TIPS_GRANULARITY;\n// ══════════════════════════════ STATEMENT SALTS ══════════════════════════════\n/// @dev Salts for signing various statements\nbytes32 constant ATTESTATION_VALID_SALT = keccak256(\"ATTESTATION_VALID_SALT\");\nbytes32 constant ATTESTATION_INVALID_SALT = keccak256(\"ATTESTATION_INVALID_SALT\");\nbytes32 constant RECEIPT_VALID_SALT = keccak256(\"RECEIPT_VALID_SALT\");\nbytes32 constant RECEIPT_INVALID_SALT = keccak256(\"RECEIPT_INVALID_SALT\");\nbytes32 constant SNAPSHOT_VALID_SALT = keccak256(\"SNAPSHOT_VALID_SALT\");\nbytes32 constant STATE_INVALID_SALT = keccak256(\"STATE_INVALID_SALT\");\n// ═════════════════════════════════ PROTOCOL ══════════════════════════════════\n/// @dev Optimistic period for new agent roots in LightManager\nuint32 constant AGENT_ROOT_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Timeout between the agent root could be proposed and resolved in LightManager\nuint32 constant AGENT_ROOT_PROPOSAL_TIMEOUT = 12 hours;\nuint32 constant BONDING_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Amount of time that the Notary will not be considered active after they won a dispute\nuint32 constant DISPUTE_TIMEOUT_NOTARY = 12 hours;\n/// @dev Amount of time without fresh data from Notaries before contract owner can resolve stuck disputes manually\nuint256 constant FRESH_DATA_TIMEOUT = 4 hours;\n/// @dev Maximum bytes per message = 2 KiB (somewhat arbitrarily set to begin)\nuint256 constant MAX_CONTENT_BYTES = 2 * 2 ** 10;\n/// @dev Maximum value for the summit tip that could be set in GasOracle\nuint256 constant MAX_SUMMIT_TIP = 0.01 ether;\n\n// contracts/libs/Errors.sol\n\n// ══════════════════════════════ INVALID CALLER ═══════════════════════════════\n\nerror CallerNotAgentManager();\nerror CallerNotDestination();\nerror CallerNotInbox();\nerror CallerNotSummit();\n\n// ══════════════════════════════ INCORRECT DATA ═══════════════════════════════\n\nerror IncorrectAttestation();\nerror IncorrectAgentDomain();\nerror IncorrectAgentIndex();\nerror IncorrectAgentProof();\nerror IncorrectAgentRoot();\nerror IncorrectDataHash();\nerror IncorrectDestinationDomain();\nerror IncorrectOriginDomain();\nerror IncorrectSnapshotProof();\nerror IncorrectSnapshotRoot();\nerror IncorrectState();\nerror IncorrectStatesAmount();\nerror IncorrectTipsProof();\nerror IncorrectVersionLength();\n\nerror IncorrectNonce();\nerror IncorrectSender();\nerror IncorrectRecipient();\n\nerror FlagOutOfRange();\nerror IndexOutOfRange();\nerror NonceOutOfRange();\n\nerror OutdatedNonce();\n\nerror UnformattedAttestation();\nerror UnformattedAttestationReport();\nerror UnformattedBaseMessage();\nerror UnformattedCallData();\nerror UnformattedCallDataPrefix();\nerror UnformattedMessage();\nerror UnformattedReceipt();\nerror UnformattedReceiptReport();\nerror UnformattedSignature();\nerror UnformattedSnapshot();\nerror UnformattedState();\nerror UnformattedStateReport();\n\n// ═══════════════════════════════ MERKLE TREES ════════════════════════════════\n\nerror LeafNotProven();\nerror MerkleTreeFull();\nerror NotEnoughLeafs();\nerror TreeHeightTooLow();\n\n// ═════════════════════════════ OPTIMISTIC PERIOD ═════════════════════════════\n\nerror BaseClientOptimisticPeriod();\nerror MessageOptimisticPeriod();\nerror SlashAgentOptimisticPeriod();\nerror WithdrawTipsOptimisticPeriod();\nerror ZeroProofMaturity();\n\n// ═══════════════════════════════ AGENT MANAGER ═══════════════════════════════\n\nerror AgentNotGuard();\nerror AgentNotNotary();\n\nerror AgentCantBeAdded();\nerror AgentNotActive();\nerror AgentNotActiveNorUnstaking();\nerror AgentNotFraudulent();\nerror AgentNotUnstaking();\nerror AgentUnknown();\n\nerror AgentRootNotProposed();\nerror AgentRootTimeoutNotOver();\n\nerror NotStuck();\n\nerror DisputeAlreadyResolved();\nerror DisputeNotOpened();\nerror DisputeTimeoutNotOver();\nerror GuardInDispute();\nerror NotaryInDispute();\n\nerror MustBeSynapseDomain();\nerror SynapseDomainForbidden();\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\nerror AlreadyExecuted();\nerror AlreadyFailed();\nerror DuplicatedSnapshotRoot();\nerror IncorrectMagicValue();\nerror GasLimitTooLow();\nerror GasSuppliedTooLow();\n\n// ══════════════════════════════════ ORIGIN ═══════════════════════════════════\n\nerror ContentLengthTooBig();\nerror EthTransferFailed();\nerror InsufficientEthBalance();\n\n// ════════════════════════════════ GAS ORACLE ═════════════════════════════════\n\nerror LocalGasDataNotSet();\nerror RemoteGasDataNotSet();\n\n// ═══════════════════════════════════ TIPS ════════════════════════════════════\n\nerror SummitTipTooHigh();\nerror TipsClaimMoreThanEarned();\nerror TipsClaimZero();\nerror TipsOverflow();\nerror TipsValueTooLow();\n\n// ════════════════════════════════ MEMORY VIEW ════════════════════════════════\n\nerror IndexedTooMuch();\nerror ViewOverrun();\nerror OccupiedMemory();\nerror UnallocatedMemory();\nerror PrecompileOutOfGas();\n\n// ═════════════════════════════════ MULTICALL ═════════════════════════════════\n\nerror MulticallFailed();\n\n// contracts/libs/TypeCasts.sol\n\nlibrary TypeCasts {\n    // alignment preserving cast\n    function addressToBytes32(address addr) internal pure returns (bytes32) {\n        return bytes32(uint256(uint160(addr)));\n    }\n\n    // alignment preserving cast\n    function bytes32ToAddress(bytes32 buf) internal pure returns (address) {\n        return address(uint160(uint256(buf)));\n    }\n}\n\n// contracts/libs/stack/Number.sol\n\n/// Number is a compact representation of uint256, that is fit into 16 bits\n/// with the maximum relative error under 0.4%.\ntype Number is uint16;\n\nusing NumberLib for Number global;\n\n/// # Number\n/// Library for compact representation of uint256 numbers.\n/// - Number is stored using mantissa and exponent, each occupying 8 bits.\n/// - Numbers under 2**8 are stored as `mantissa` with `exponent = 0xFF`.\n/// - Numbers at least 2**8 are approximated as `(256 + mantissa) \u003c\u003c exponent`\n/// \u003e - `0 \u003c= mantissa \u003c 256`\n/// \u003e - `0 \u003c= exponent \u003c= 247` (`256 * 2**248` doesn't fit into uint256)\n/// # Number stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type  | Bytes |\n/// | ---------- | -------- | ----- | ----- |\n/// | (002..001] | mantissa | uint8 | 1     |\n/// | (001..000] | exponent | uint8 | 1     |\n\nlibrary NumberLib {\n    /// @dev Amount of bits to shift to mantissa field\n    uint16 private constant SHIFT_MANTISSA = 8;\n\n    /// @notice For bwad math (binary wad) we use 2**64 as \"wad\" unit.\n    /// @dev We are using not using 10**18 as wad, because it is not stored precisely in NumberLib.\n    uint256 internal constant BWAD_SHIFT = 64;\n    uint256 internal constant BWAD = 1 \u003c\u003c BWAD_SHIFT;\n    /// @notice ~0.1% in bwad units.\n    uint256 internal constant PER_MILLE_SHIFT = BWAD_SHIFT - 10;\n    uint256 internal constant PER_MILLE = 1 \u003c\u003c PER_MILLE_SHIFT;\n\n    /// @notice Compresses uint256 number into 16 bits.\n    function compress(uint256 value) internal pure returns (Number) {\n        // Find `msb` such as `2**msb \u003c= value \u003c 2**(msb + 1)`\n        uint256 msb = mostSignificantBit(value);\n        // We want to preserve 9 bits of precision.\n        // The highest bit is always 1, so we can skip it.\n        // The remaining 8 highest bits are stored as mantissa.\n        if (msb \u003c 8) {\n            // Value is less than 2**8, so we can use value as mantissa with \"-1\" exponent.\n            return _encode(uint8(value), 0xFF);\n        } else {\n            // We use `msb - 8` as exponent otherwise. Note that `exponent \u003e= 0`.\n            unchecked {\n                uint256 exponent = msb - 8;\n                // Shifting right by `msb-8` bits will shift the \"remaining 8 highest bits\" into the 8 lowest bits.\n                // uint8() will truncate the highest bit.\n                return _encode(uint8(value \u003e\u003e exponent), uint8(exponent));\n            }\n        }\n    }\n\n    /// @notice Decompresses 16 bits number into uint256.\n    /// @dev The outcome is an approximation of the original number: `(value - value / 256) \u003c number \u003c= value`.\n    function decompress(Number number) internal pure returns (uint256 value) {\n        // Isolate 8 highest bits as the mantissa.\n        uint256 mantissa = Number.unwrap(number) \u003e\u003e SHIFT_MANTISSA;\n        // This will truncate the highest bits, leaving only the exponent.\n        uint256 exponent = uint8(Number.unwrap(number));\n        if (exponent == 0xFF) {\n            return mantissa;\n        } else {\n            unchecked {\n                return (256 + mantissa) \u003c\u003c (exponent);\n            }\n        }\n    }\n\n    /// @dev Returns the most significant bit of `x`\n    /// https://solidity-by-example.org/bitwise/\n    function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\n        // To find `msb` we determine it bit by bit, starting from the highest one.\n        // `0 \u003c= msb \u003c= 255`, so we start from the highest bit, 1\u003c\u003c7 == 128.\n        // If `x` is at least 2**128, then the highest bit of `x` is at least 128.\n        // solhint-disable no-inline-assembly\n        assembly {\n            // `f` is set to 1\u003c\u003c7 if `x \u003e= 2**128` and to 0 otherwise.\n            let f := shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\n            // If `x \u003e= 2**128` then set `msb` highest bit to 1 and shift `x` right by 128.\n            // Otherwise, `msb` remains 0 and `x` remains unchanged.\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        // `x` is now at most 2**128 - 1. Continue the same way, the next highest bit is 1\u003c\u003c6 == 64.\n        assembly {\n            // `f` is set to 1\u003c\u003c6 if `x \u003e= 2**64` and to 0 otherwise.\n            let f := shl(6, gt(x, 0xFFFFFFFFFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c5 if `x \u003e= 2**32` and to 0 otherwise.\n            let f := shl(5, gt(x, 0xFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c4 if `x \u003e= 2**16` and to 0 otherwise.\n            let f := shl(4, gt(x, 0xFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c3 if `x \u003e= 2**8` and to 0 otherwise.\n            let f := shl(3, gt(x, 0xFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c2 if `x \u003e= 2**4` and to 0 otherwise.\n            let f := shl(2, gt(x, 0xF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c1 if `x \u003e= 2**2` and to 0 otherwise.\n            let f := shl(1, gt(x, 0x3))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1 if `x \u003e= 2**1` and to 0 otherwise.\n            let f := gt(x, 0x1)\n            msb := or(msb, f)\n        }\n    }\n\n    /// @dev Wraps (mantissa, exponent) pair into Number.\n    function _encode(uint8 mantissa, uint8 exponent) private pure returns (Number) {\n        // Casts below are upcasts, so they are safe.\n        return Number.wrap(uint16(mantissa) \u003c\u003c SHIFT_MANTISSA | uint16(exponent));\n    }\n}\n\n// contracts/libs/stack/Request.sol\n\n/// Request is encoded data with \"message execution request\".\ntype Request is uint192;\n\nusing RequestLib for Request global;\n\n/// Library for formatting _the request part_ of _the base messages_.\n/// - Request represents a message sender requirements for the message execution on the destination chain.\n/// - Request occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n/// \u003e gasDrop field is included for future compatibility and is ignored at the moment.\n///\n/// # Request stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type   | Bytes | Description                                          |\n/// | ---------- | -------- | ------ | ----- | ---------------------------------------------------- |\n/// | (024..012] | gasDrop  | uint96 | 12    | Minimum amount of gas token to drop to the recipient |\n/// | (012..004] | gasLimit | uint64 | 8     | Minimum amount of gas units to supply for execution  |\n/// | (004..000] | version  | uint32 | 4     | Base message version to pass to the recipient        |\n\nlibrary RequestLib {\n    /// @dev Amount of bits to shift to gasDrop field\n    uint192 private constant SHIFT_GAS_DROP = 12 * 8;\n    /// @dev Amount of bits to shift to gasLimit field\n    uint192 private constant SHIFT_GAS_LIMIT = 4 * 8;\n\n    /// @notice Returns an encoded request with the given fields\n    /// @param gasDrop_     Minimum amount of gas token to drop to the recipient (ignored at the moment)\n    /// @param gasLimit_    Minimum amount of gas units to supply for execution\n    /// @param version_     Base message version to pass to the recipient\n    function encodeRequest(uint96 gasDrop_, uint64 gasLimit_, uint32 version_) internal pure returns (Request) {\n        // Casts below are upcasts, so they are safe\n        return Request.wrap(uint192(gasDrop_) \u003c\u003c SHIFT_GAS_DROP | uint192(gasLimit_) \u003c\u003c SHIFT_GAS_LIMIT | version_);\n    }\n\n    /// @notice Wraps the padded encoded request into a Request-typed value.\n    /// @dev The \"padded\" request is simply an encoded request casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded requests\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedRequest) internal pure returns (Request) {\n        // Casting to uint192 will truncate the highest bits, which is the behavior we want\n        return Request.wrap(uint192(paddedRequest));\n    }\n\n    /// @notice Returns the requested of gas token to drop to the recipient.\n    function gasDrop(Request request) internal pure returns (uint96) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return uint96(Request.unwrap(request) \u003e\u003e SHIFT_GAS_DROP);\n    }\n\n    /// @notice Returns the requested minimum amount of gas units to supply for execution.\n    function gasLimit(Request request) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Request.unwrap(request) \u003e\u003e SHIFT_GAS_LIMIT);\n    }\n\n    /// @notice Returns the requested base message version to pass to the recipient.\n    function version(Request request) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Request.unwrap(request));\n    }\n}\n\n// node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        require(value \u003c= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        require(value \u003c= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        require(value \u003c= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value \u003c= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        require(value \u003c= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        require(value \u003c= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        require(value \u003c= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        require(value \u003c= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        require(value \u003c= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        require(value \u003c= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        require(value \u003c= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        require(value \u003c= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        require(value \u003c= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        require(value \u003c= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        require(value \u003c= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value \u003c= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        require(value \u003c= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        require(value \u003c= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        require(value \u003c= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value \u003c= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        require(value \u003c= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        require(value \u003c= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        require(value \u003c= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value \u003c= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        require(value \u003c= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        require(value \u003c= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        require(value \u003c= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value \u003c= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        require(value \u003c= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value \u003c= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value \u003c= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     *\n     * _Available since v3.0._\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value \u003e= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     *\n     * _Available since v3.0._\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value \u003c= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     *\n     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length \u003e 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance \u003e= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance \u003e= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length \u003e 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n\n// contracts/base/MultiCallable.sol\n\n/// @notice Collection of Multicall utilities. Fork of Multicall3:\n/// https://github.com/mds1/multicall/blob/master/src/Multicall3.sol\nabstract contract MultiCallable {\n    struct Call {\n        bool allowFailure;\n        bytes callData;\n    }\n\n    struct Result {\n        bool success;\n        bytes returnData;\n    }\n\n    /// @notice Aggregates a few calls to this contract into one multicall without modifying `msg.sender`.\n    function multicall(Call[] calldata calls) external returns (Result[] memory callResults) {\n        uint256 amount = calls.length;\n        callResults = new Result[](amount);\n        Call calldata call_;\n        for (uint256 i = 0; i \u003c amount;) {\n            call_ = calls[i];\n            Result memory result = callResults[i];\n            // We perform a delegate call to ourselves here. Delegate call does not modify `msg.sender`, so\n            // this will have the same effect as if `msg.sender` performed all the calls themselves one by one.\n            // solhint-disable-next-line avoid-low-level-calls\n            (result.success, result.returnData) = address(this).delegatecall(call_.callData);\n            // solhint-disable-next-line no-inline-assembly\n            assembly {\n                // Revert if the call fails and failure is not allowed\n                // `allowFailure := calldataload(call_)` and `success := mload(result)`\n                if iszero(or(calldataload(call_), mload(result))) {\n                    // Revert with `0x4d6a2328` (function selector for `MulticallFailed()`)\n                    mstore(0x00, 0x4d6a232800000000000000000000000000000000000000000000000000000000)\n                    revert(0x00, 0x04)\n                }\n            }\n            unchecked {\n                ++i;\n            }\n        }\n    }\n}\n\n// contracts/base/Version.sol\n\n/**\n * @title Versioned\n * @notice Version getter for contracts. Doesn't use any storage slots, meaning\n * it will never cause any troubles with the upgradeable contracts. For instance, this contract\n * can be added or removed from the inheritance chain without shifting the storage layout.\n */\nabstract contract Versioned {\n    /**\n     * @notice Struct that is mimicking the storage layout of a string with 32 bytes or less.\n     * Length is limited by 32, so the whole string payload takes two memory words:\n     * @param length    String length\n     * @param data      String characters\n     */\n    struct _ShortString {\n        uint256 length;\n        bytes32 data;\n    }\n\n    /// @dev Length of the \"version string\"\n    uint256 private immutable _length;\n    /// @dev Bytes representation of the \"version string\".\n    /// Strings with length over 32 are not supported!\n    bytes32 private immutable _data;\n\n    constructor(string memory version_) {\n        _length = bytes(version_).length;\n        if (_length \u003e 32) revert IncorrectVersionLength();\n        // bytes32 is left-aligned =\u003e this will store the byte representation of the string\n        // with the trailing zeroes to complete the 32-byte word\n        _data = bytes32(bytes(version_));\n    }\n\n    function version() external view returns (string memory versionString) {\n        // Load the immutable values to form the version string\n        _ShortString memory str = _ShortString(_length, _data);\n        // The only way to do this cast is doing some dirty assembly\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            versionString := str\n        }\n    }\n}\n\n// contracts/libs/ChainContext.sol\n\n/// @notice Library for accessing chain context variables as tightly packed integers.\n/// Messaging contracts should rely on this library for accessing chain context variables\n/// instead of doing the casting themselves.\nlibrary ChainContext {\n    using SafeCast for uint256;\n\n    /// @notice Returns the current block number as uint40.\n    /// @dev Reverts if block number is greater than 40 bits, which is not supposed to happen\n    /// until the block.timestamp overflows (assuming block time is at least 1 second).\n    function blockNumber() internal view returns (uint40) {\n        return block.number.toUint40();\n    }\n\n    /// @notice Returns the current block timestamp as uint40.\n    /// @dev Reverts if block timestamp is greater than 40 bits, which is\n    /// supposed to happen approximately in year 36835.\n    function blockTimestamp() internal view returns (uint40) {\n        return block.timestamp.toUint40();\n    }\n\n    /// @notice Returns the chain id as uint32.\n    /// @dev Reverts if chain id is greater than 32 bits, which is not\n    /// supposed to happen in production.\n    function chainId() internal view returns (uint32) {\n        return block.chainid.toUint32();\n    }\n}\n\n// contracts/libs/Structures.sol\n\n// Here we define common enums and structures to enable their easier reusing later.\n\n// ═══════════════════════════════ AGENT STATUS ════════════════════════════════\n\n/// @dev Potential statuses for the off-chain bonded agent:\n/// - Unknown: never provided a bond =\u003e signature not valid\n/// - Active: has a bond in BondingManager =\u003e signature valid\n/// - Unstaking: has a bond in BondingManager, initiated the unstaking =\u003e signature not valid\n/// - Resting: used to have a bond in BondingManager, successfully unstaked =\u003e signature not valid\n/// - Fraudulent: proven to commit fraud, value in Merkle Tree not updated =\u003e signature not valid\n/// - Slashed: proven to commit fraud, value in Merkle Tree was updated =\u003e signature not valid\n/// Unstaked agent could later be added back to THE SAME domain by staking a bond again.\n/// Honest agent: Unknown -\u003e Active -\u003e unstaking -\u003e Resting -\u003e Active ...\n/// Malicious agent: Unknown -\u003e Active -\u003e Fraudulent -\u003e Slashed\n/// Malicious agent: Unknown -\u003e Active -\u003e Unstaking -\u003e Fraudulent -\u003e Slashed\nenum AgentFlag {\n    Unknown,\n    Active,\n    Unstaking,\n    Resting,\n    Fraudulent,\n    Slashed\n}\n\n/// @notice Struct for storing an agent in the BondingManager contract.\nstruct AgentStatus {\n    AgentFlag flag;\n    uint32 domain;\n    uint32 index;\n}\n// 184 bits available for tight packing\n\nusing StructureUtils for AgentStatus global;\n\n/// @notice Potential statuses of an agent in terms of being in dispute\n/// - None: agent is not in dispute\n/// - Pending: agent is in unresolved dispute\n/// - Slashed: agent was in dispute that lead to agent being slashed\n/// Note: agent who won the dispute has their status reset to None\nenum DisputeFlag {\n    None,\n    Pending,\n    Slashed\n}\n\n/// @notice Struct for storing dispute status of an agent.\n/// @param flag         Dispute flag: None/Pending/Slashed.\n/// @param openedAt     Timestamp when the latest agent dispute was opened (zero if not opened).\n/// @param resolvedAt   Timestamp when the latest agent dispute was resolved (zero if not resolved).\nstruct DisputeStatus {\n    DisputeFlag flag;\n    uint40 openedAt;\n    uint40 resolvedAt;\n}\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\n/// @notice Struct representing the status of Destination contract.\n/// @param snapRootTime     Timestamp when latest snapshot root was accepted\n/// @param agentRootTime    Timestamp when latest agent root was accepted\n/// @param notaryIndex      Index of Notary who signed the latest agent root\nstruct DestinationStatus {\n    uint40 snapRootTime;\n    uint40 agentRootTime;\n    uint32 notaryIndex;\n}\n\n// ═══════════════════════════════ EXECUTION HUB ═══════════════════════════════\n\n/// @notice Potential statuses of the message in Execution Hub.\n/// - None: there hasn't been a valid attempt to execute the message yet\n/// - Failed: there was a valid attempt to execute the message, but recipient reverted\n/// - Success: there was a valid attempt to execute the message, and recipient did not revert\n/// Note: message can be executed until its status is Success\nenum MessageStatus {\n    None,\n    Failed,\n    Success\n}\n\nlibrary StructureUtils {\n    /// @notice Checks that Agent is Active\n    function verifyActive(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active) {\n            revert AgentNotActive();\n        }\n    }\n\n    /// @notice Checks that Agent is Unstaking\n    function verifyUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Unstaking) {\n            revert AgentNotUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Active or Unstaking\n    function verifyActiveUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active \u0026\u0026 status.flag != AgentFlag.Unstaking) {\n            revert AgentNotActiveNorUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Fraudulent\n    function verifyFraudulent(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Fraudulent) {\n            revert AgentNotFraudulent();\n        }\n    }\n\n    /// @notice Checks that Agent is not Unknown\n    function verifyKnown(AgentStatus memory status) internal pure {\n        if (status.flag == AgentFlag.Unknown) {\n            revert AgentUnknown();\n        }\n    }\n}\n\n// contracts/libs/memory/MemView.sol\n\n/// @dev MemView is an untyped view over a portion of memory to be used instead of `bytes memory`\ntype MemView is uint256;\n\n/// @dev Attach library functions to MemView\nusing MemViewLib for MemView global;\n\n/// @notice Library for operations with the memory views.\n/// Forked from https://github.com/summa-tx/memview-sol with several breaking changes:\n/// - The codebase is ported to Solidity 0.8\n/// - Custom errors are added\n/// - The runtime type checking is replaced with compile-time check provided by User-Defined Value Types\n///   https://docs.soliditylang.org/en/latest/types.html#user-defined-value-types\n/// - uint256 is used as the underlying type for the \"memory view\" instead of bytes29.\n///   It is wrapped into MemView custom type in order not to be confused with actual integers.\n/// - Therefore the \"type\" field is discarded, allowing to allocate 16 bytes for both view location and length\n/// - The documentation is expanded\n/// - Library functions unused by the rest of the codebase are removed\n//  - Very pretty code separators are added :)\nlibrary MemViewLib {\n    /// @notice Stack layout for uint256 (from highest bits to lowest)\n    /// (32 .. 16]      loc     16 bytes    Memory address of underlying bytes\n    /// (16 .. 00]      len     16 bytes    Length of underlying bytes\n\n    // ═══════════════════════════════════════════ BUILDING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Instantiate a new untyped memory view. This should generally not be called directly.\n     * Prefer `ref` wherever possible.\n     * @param loc_          The memory address\n     * @param len_          The length\n     * @return The new view with the specified location and length\n     */\n    function build(uint256 loc_, uint256 len_) internal pure returns (MemView) {\n        uint256 end_ = loc_ + len_;\n        // Make sure that a view is not constructed that points to unallocated memory\n        // as this could be indicative of a buffer overflow attack\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            if gt(end_, mload(0x40)) { end_ := 0 }\n        }\n        if (end_ == 0) {\n            revert UnallocatedMemory();\n        }\n        return _unsafeBuildUnchecked(loc_, len_);\n    }\n\n    /**\n     * @notice Instantiate a memory view from a byte array.\n     * @dev Note that due to Solidity memory representation, it is not possible to\n     * implement a deref, as the `bytes` type stores its len in memory.\n     * @param arr           The byte array\n     * @return The memory view over the provided byte array\n     */\n    function ref(bytes memory arr) internal pure returns (MemView) {\n        uint256 len_ = arr.length;\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 loc_;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // We add 0x20, so that the view starts exactly where the array data starts\n            loc_ := add(arr, 0x20)\n        }\n        return build(loc_, len_);\n    }\n\n    // ════════════════════════════════════════════ CLONING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to the new memory.\n     * @param memView       The memory view\n     * @return arr          The cloned byte array\n     */\n    function clone(MemView memView) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        unchecked {\n            _unsafeCopyTo(memView, ptr + 0x20);\n        }\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 len_ = memView.len();\n        uint256 footprint_ = memView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    /**\n     * @notice Copies all views, joins them into a new bytearray.\n     * @param memViews      The memory views\n     * @return arr          The new byte array with joined data behind the given views\n     */\n    function join(MemView[] memory memViews) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        MemView newView;\n        unchecked {\n            newView = _unsafeJoin(memViews, ptr + 0x20);\n        }\n        uint256 len_ = newView.len();\n        uint256 footprint_ = newView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    // ══════════════════════════════════════════ INSPECTING MEMORY VIEW ═══════════════════════════════════════════════\n\n    /**\n     * @notice Returns the memory address of the underlying bytes.\n     * @param memView       The memory view\n     * @return loc_         The memory address\n     */\n    function loc(MemView memView) internal pure returns (uint256 loc_) {\n        // loc is stored in the highest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u003e\u003e 128;\n    }\n\n    /**\n     * @notice Returns the number of bytes of the view.\n     * @param memView       The memory view\n     * @return len_         The length of the view\n     */\n    function len(MemView memView) internal pure returns (uint256 len_) {\n        // len is stored in the lowest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u0026 type(uint128).max;\n    }\n\n    /**\n     * @notice Returns the endpoint of `memView`.\n     * @param memView       The memory view\n     * @return end_         The endpoint of `memView`\n     */\n    function end(MemView memView) internal pure returns (uint256 end_) {\n        // The endpoint never overflows uint128, let alone uint256, so we could use unchecked math here\n        unchecked {\n            return memView.loc() + memView.len();\n        }\n    }\n\n    /**\n     * @notice Returns the number of memory words this memory view occupies, rounded up.\n     * @param memView       The memory view\n     * @return words_       The number of memory words\n     */\n    function words(MemView memView) internal pure returns (uint256 words_) {\n        // returning ceil(length / 32.0)\n        unchecked {\n            return (memView.len() + 31) \u003e\u003e 5;\n        }\n    }\n\n    /**\n     * @notice Returns the in-memory footprint of a fresh copy of the view.\n     * @param memView       The memory view\n     * @return footprint_   The in-memory footprint of a fresh copy of the view.\n     */\n    function footprint(MemView memView) internal pure returns (uint256 footprint_) {\n        // words() * 32\n        return memView.words() \u003c\u003c 5;\n    }\n\n    // ════════════════════════════════════════════ HASHING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the keccak256 hash of the underlying memory\n     * @param memView       The memory view\n     * @return digest       The keccak256 hash of the underlying memory\n     */\n    function keccak(MemView memView) internal pure returns (bytes32 digest) {\n        uint256 loc_ = memView.loc();\n        uint256 len_ = memView.len();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            digest := keccak256(loc_, len_)\n        }\n    }\n\n    /**\n     * @notice Adds a salt to the keccak256 hash of the underlying data and returns the keccak256 hash of the\n     * resulting data.\n     * @param memView       The memory view\n     * @return digestSalted keccak256(salt, keccak256(memView))\n     */\n    function keccakSalted(MemView memView, bytes32 salt) internal pure returns (bytes32 digestSalted) {\n        return keccak256(bytes.concat(salt, memView.keccak()));\n    }\n\n    // ════════════════════════════════════════════ SLICING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Safe slicing without memory modification.\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the given index\n     */\n    function slice(MemView memView, uint256 index_, uint256 len_) internal pure returns (MemView) {\n        uint256 loc_ = memView.loc();\n        // Ensure it doesn't overrun the view\n        if (loc_ + index_ + len_ \u003e memView.end()) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // loc_ + index_ \u003c= memView.end()\n            return build({loc_: loc_ + index_, len_: len_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing bytes from `index` to end(memView).\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @return The new view for the slice starting from the given index until the initial view endpoint\n     */\n    function sliceFrom(MemView memView, uint256 index_) internal pure returns (MemView) {\n        uint256 len_ = memView.len();\n        // Ensure it doesn't overrun the view\n        if (index_ \u003e len_) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // index_ \u003c= len_ =\u003e memView.loc() + index_ \u003c= memView.loc() + memView.len() == memView.end()\n            return build({loc_: memView.loc() + index_, len_: len_ - index_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the first `len` bytes.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the initial view beginning\n     */\n    function prefix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        return memView.slice({index_: 0, len_: len_});\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the last `len` byte.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length until the initial view endpoint\n     */\n    function postfix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        uint256 viewLen = memView.len();\n        // Ensure it doesn't overrun the view\n        if (len_ \u003e viewLen) {\n            revert ViewOverrun();\n        }\n        // Could do the unchecked math due to the check above\n        uint256 index_;\n        unchecked {\n            index_ = viewLen - len_;\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // len_ \u003c= memView.len() =\u003e memView.loc() \u003c= loc_ \u003c= memView.end()\n            return build({loc_: memView.loc() + viewLen - len_, len_: len_});\n        }\n    }\n\n    // ═══════════════════════════════════════════ INDEXING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Load up to 32 bytes from the view onto the stack.\n     * @dev Returns a bytes32 with only the `bytes_` HIGHEST bytes set.\n     * This can be immediately cast to a smaller fixed-length byte array.\n     * To automatically cast to an integer, use `indexUint`.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return result       The 32 byte result having only `bytes_` highest bytes set\n     */\n    function index(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (bytes32 result) {\n        if (bytes_ == 0) {\n            return bytes32(0);\n        }\n        // Can't load more than 32 bytes to the stack in one go\n        if (bytes_ \u003e 32) {\n            revert IndexedTooMuch();\n        }\n        // The last indexed byte should be within view boundaries\n        if (index_ + bytes_ \u003e memView.len()) {\n            revert ViewOverrun();\n        }\n        uint256 bitLength = bytes_ \u003c\u003c 3; // bytes_ * 8\n        uint256 loc_ = memView.loc();\n        // Get a mask with `bitLength` highest bits set\n        uint256 mask;\n        // 0x800...00 binary representation is 100...00\n        // sar stands for \"signed arithmetic shift\": https://en.wikipedia.org/wiki/Arithmetic_shift\n        // sar(N-1, 100...00) = 11...100..00, with exactly N highest bits set to 1\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            mask := sar(sub(bitLength, 1), 0x8000000000000000000000000000000000000000000000000000000000000000)\n        }\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load a full word using index offset, and apply mask to ignore non-relevant bytes\n            result := and(mload(add(loc_, index_)), mask)\n        }\n    }\n\n    /**\n     * @notice Parse an unsigned integer from the view at `index`.\n     * @dev Requires that the view have \u003e= `bytes_` bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return The unsigned integer\n     */\n    function indexUint(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (uint256) {\n        bytes32 indexedBytes = memView.index(index_, bytes_);\n        // `index()` returns left-aligned `bytes_`, while integers are right-aligned\n        // Shifting here to right-align with the full 32 bytes word: need to shift right `(32 - bytes_)` bytes\n        unchecked {\n            // memView.index() reverts when bytes_ \u003e 32, thus unchecked math\n            return uint256(indexedBytes) \u003e\u003e ((32 - bytes_) \u003c\u003c 3);\n        }\n    }\n\n    /**\n     * @notice Parse an address from the view at `index`.\n     * @dev Requires that the view have \u003e= 20 bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @return The address\n     */\n    function indexAddress(MemView memView, uint256 index_) internal pure returns (address) {\n        // index 20 bytes as `uint160`, and then cast to `address`\n        return address(uint160(memView.indexUint(index_, 20)));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns a memory view over the specified memory location\n    /// without checking if it points to unallocated memory.\n    function _unsafeBuildUnchecked(uint256 loc_, uint256 len_) private pure returns (MemView) {\n        // There is no scenario where loc or len would overflow uint128, so we omit this check.\n        // We use the highest 128 bits to encode the location and the lowest 128 bits to encode the length.\n        return MemView.wrap((loc_ \u003c\u003c 128) | len_);\n    }\n\n    /**\n     * @notice Copy the view to a location, return an unsafe memory reference\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memView       The memory view\n     * @param newLoc        The new location to copy the underlying view data\n     * @return The memory view over the unsafe memory with the copied underlying data\n     */\n    function _unsafeCopyTo(MemView memView, uint256 newLoc) private view returns (MemView) {\n        uint256 len_ = memView.len();\n        uint256 oldLoc = memView.loc();\n\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (newLoc \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        bool res;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // use the identity precompile (0x04) to copy\n            res := staticcall(gas(), 0x04, oldLoc, len_, newLoc, len_)\n        }\n        if (!res) revert PrecompileOutOfGas();\n        return _unsafeBuildUnchecked({loc_: newLoc, len_: len_});\n    }\n\n    /**\n     * @notice Join the views in memory, return an unsafe reference to the memory.\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memViews      The memory views\n     * @return The conjoined view pointing to the new memory\n     */\n    function _unsafeJoin(MemView[] memory memViews, uint256 location) private view returns (MemView) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (location \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        // Copy the views to the specified location one by one, by tracking the amount of copied bytes so far\n        uint256 offset = 0;\n        for (uint256 i = 0; i \u003c memViews.length;) {\n            MemView memView = memViews[i];\n            // We can use the unchecked math here as location + sum(view.length) will never overflow uint256\n            unchecked {\n                _unsafeCopyTo(memView, location + offset);\n                offset += memView.len();\n                ++i;\n            }\n        }\n        return _unsafeBuildUnchecked({loc_: location, len_: offset});\n    }\n}\n\n// contracts/libs/merkle/MerkleMath.sol\n\nlibrary MerkleMath {\n    // ═════════════════════════════════════════ BASIC MERKLE CALCULATIONS ═════════════════════════════════════════════\n\n    /**\n     * @notice Calculates the merkle root for the given leaf and merkle proof.\n     * @dev Will revert if proof length exceeds the tree height.\n     * @param index     Index of `leaf` in tree\n     * @param leaf      Leaf of the merkle tree\n     * @param proof     Proof of inclusion of `leaf` in the tree\n     * @param height    Height of the merkle tree\n     * @return root_    Calculated Merkle Root\n     */\n    function proofRoot(uint256 index, bytes32 leaf, bytes32[] memory proof, uint256 height)\n        internal\n        pure\n        returns (bytes32 root_)\n    {\n        // Proof length could not exceed the tree height\n        uint256 proofLen = proof.length;\n        if (proofLen \u003e height) revert TreeHeightTooLow();\n        root_ = leaf;\n        /// @dev Apply unchecked to all ++h operations\n        unchecked {\n            // Go up the tree levels from the leaf following the proof\n            for (uint256 h = 0; h \u003c proofLen; ++h) {\n                // Get a sibling node on current level: this is proof[h]\n                root_ = getParent(root_, proof[h], index, h);\n            }\n            // Go up to the root: the remaining siblings are EMPTY\n            for (uint256 h = proofLen; h \u003c height; ++h) {\n                root_ = getParent(root_, bytes32(0), index, h);\n            }\n        }\n    }\n\n    /**\n     * @notice Calculates the parent of a node on the path from one of the leafs to root.\n     * @param node          Node on a path from tree leaf to root\n     * @param sibling       Sibling for a given node\n     * @param leafIndex     Index of the tree leaf\n     * @param nodeHeight    \"Level height\" for `node` (ZERO for leafs, ORIGIN_TREE_HEIGHT for root)\n     */\n    function getParent(bytes32 node, bytes32 sibling, uint256 leafIndex, uint256 nodeHeight)\n        internal\n        pure\n        returns (bytes32 parent)\n    {\n        // Index for `node` on its \"tree level\" is (leafIndex / 2**height)\n        // \"Left child\" has even index, \"right child\" has odd index\n        if ((leafIndex \u003e\u003e nodeHeight) \u0026 1 == 0) {\n            // Left child\n            return getParent(node, sibling);\n        } else {\n            // Right child\n            return getParent(sibling, node);\n        }\n    }\n\n    /// @notice Calculates the parent of tow nodes in the merkle tree.\n    /// @dev We use implementation with H(0,0) = 0\n    /// This makes EVERY empty node in the tree equal to ZERO,\n    /// saving us from storing H(0,0), H(H(0,0), H(0, 0)), and so on\n    /// @param leftChild    Left child of the calculated node\n    /// @param rightChild   Right child of the calculated node\n    /// @return parent      Value for the node having above mentioned children\n    function getParent(bytes32 leftChild, bytes32 rightChild) internal pure returns (bytes32 parent) {\n        if (leftChild == bytes32(0) \u0026\u0026 rightChild == bytes32(0)) {\n            return 0;\n        } else {\n            return keccak256(bytes.concat(leftChild, rightChild));\n        }\n    }\n\n    // ════════════════════════════════ ROOT/PROOF CALCULATION FOR A LIST OF LEAFS ═════════════════════════════════════\n\n    /**\n     * @notice Calculates merkle root for a list of given leafs.\n     * Merkle Tree is constructed by padding the list with ZERO values for leafs until list length is `2**height`.\n     * Merkle Root is calculated for the constructed tree, and then saved in `leafs[0]`.\n     * \u003e Note:\n     * \u003e - `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * \u003e - Caller is expected not to reuse `hashes` list after the call, and only use `leafs[0]` value,\n     * which is guaranteed to contain the calculated merkle root.\n     * \u003e - root is calculated using the `H(0,0) = 0` Merkle Tree implementation. See MerkleTree.sol for details.\n     * @dev Amount of leaves should be at most `2**height`\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param height    Height of the Merkle Tree to construct\n     */\n    function calculateRoot(bytes32[] memory hashes, uint256 height) internal pure {\n        uint256 levelLength = hashes.length;\n        // Amount of hashes could not exceed amount of leafs in tree with the given height\n        if (levelLength \u003e (1 \u003c\u003c height)) revert TreeHeightTooLow();\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\": the amount of iterations for the for loop above.\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n            }\n        }\n    }\n\n    /**\n     * @notice Generates a proof of inclusion of a leaf in the list. If the requested index is outside\n     * of the list range, generates a proof of inclusion for an empty leaf (proof of non-inclusion).\n     * The Merkle Tree is constructed by padding the list with ZERO values until list length is a power of two\n     * __AND__ index is in the extended list range. For example:\n     *  - `hashes.length == 6` and `0 \u003c= index \u003c= 7` will \"extend\" the list to 8 entries.\n     *  - `hashes.length == 6` and `7 \u003c index \u003c= 15` will \"extend\" the list to 16 entries.\n     * \u003e Note: `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * Caller is expected not to reuse `hashes` list after the call.\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param index     Leaf index to generate the proof for\n     * @return proof    Generated merkle proof\n     */\n    function calculateProof(bytes32[] memory hashes, uint256 index) internal pure returns (bytes32[] memory proof) {\n        // Use only meaningful values for the shortened proof\n        // Check if index is within the list range (we want to generates proofs for outside leafs as well)\n        uint256 height = getHeight(index \u003c hashes.length ? hashes.length : (index + 1));\n        proof = new bytes32[](height);\n        uint256 levelLength = hashes.length;\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Use sibling for the merkle proof; `index^1` is index of our sibling\n                proof[h] = (index ^ 1 \u003c levelLength) ? hashes[index ^ 1] : bytes32(0);\n\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\"\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n                // Traverse to parent node\n                index \u003e\u003e= 1;\n            }\n        }\n    }\n\n    /// @notice Returns the height of the tree having a given amount of leafs.\n    function getHeight(uint256 leafs) internal pure returns (uint256 height) {\n        uint256 amount = 1;\n        while (amount \u003c leafs) {\n            unchecked {\n                ++height;\n            }\n            amount \u003c\u003c= 1;\n        }\n    }\n}\n\n// contracts/libs/stack/GasData.sol\n\n/// GasData in encoded data with \"basic information about gas prices\" for some chain.\ntype GasData is uint96;\n\nusing GasDataLib for GasData global;\n\n/// ChainGas is encoded data with given chain's \"basic information about gas prices\".\ntype ChainGas is uint128;\n\nusing GasDataLib for ChainGas global;\n\n/// Library for encoding and decoding GasData and ChainGas structs.\n/// # GasData\n/// `GasData` is a struct to store the \"basic information about gas prices\", that could\n/// be later used to approximate the cost of a message execution, and thus derive the\n/// minimal tip values for sending a message to the chain.\n/// \u003e - `GasData` is supposed to be cached by `GasOracle` contract, allowing to store the\n/// \u003e approximates instead of the exact values, and thus save on storage costs.\n/// \u003e - For instance, if `GasOracle` only updates the values on +- 10% change, having an\n/// \u003e 0.4% error on the approximates would be acceptable.\n/// `GasData` is supposed to be included in the Origin's state, which are synced across\n/// chains using Agent-signed snapshots and attestations.\n/// ## GasData stack layout (from highest bits to lowest)\n///\n/// | Position   | Field        | Type   | Bytes | Description                                         |\n/// | ---------- | ------------ | ------ | ----- | --------------------------------------------------- |\n/// | (012..010] | gasPrice     | uint16 | 2     | Gas price for the chain (in Wei per gas unit)       |\n/// | (010..008] | dataPrice    | uint16 | 2     | Calldata price (in Wei per byte of content)         |\n/// | (008..006] | execBuffer   | uint16 | 2     | Tx fee safety buffer for message execution (in Wei) |\n/// | (006..004] | amortAttCost | uint16 | 2     | Amortized cost for attestation submission (in Wei)  |\n/// | (004..002] | etherPrice   | uint16 | 2     | Chain's Ether Price / Mainnet Ether Price (in BWAD) |\n/// | (002..000] | markup       | uint16 | 2     | Markup for the message execution (in BWAD)          |\n/// \u003e See Number.sol for more details on `Number` type and BWAD (binary WAD) math.\n///\n/// ## ChainGas stack layout (from highest bits to lowest)\n///\n/// | Position   | Field   | Type   | Bytes | Description      |\n/// | ---------- | ------- | ------ | ----- | ---------------- |\n/// | (016..004] | gasData | uint96 | 12    | Chain's gas data |\n/// | (004..000] | domain  | uint32 | 4     | Chain's domain   |\nlibrary GasDataLib {\n    /// @dev Amount of bits to shift to gasPrice field\n    uint96 private constant SHIFT_GAS_PRICE = 10 * 8;\n    /// @dev Amount of bits to shift to dataPrice field\n    uint96 private constant SHIFT_DATA_PRICE = 8 * 8;\n    /// @dev Amount of bits to shift to execBuffer field\n    uint96 private constant SHIFT_EXEC_BUFFER = 6 * 8;\n    /// @dev Amount of bits to shift to amortAttCost field\n    uint96 private constant SHIFT_AMORT_ATT_COST = 4 * 8;\n    /// @dev Amount of bits to shift to etherPrice field\n    uint96 private constant SHIFT_ETHER_PRICE = 2 * 8;\n\n    /// @dev Amount of bits to shift to gasData field\n    uint128 private constant SHIFT_GAS_DATA = 4 * 8;\n\n    // ═════════════════════════════════════════════════ GAS DATA ══════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded GasData struct with the given fields.\n    /// @param gasPrice_        Gas price for the chain (in Wei per gas unit)\n    /// @param dataPrice_       Calldata price (in Wei per byte of content)\n    /// @param execBuffer_      Tx fee safety buffer for message execution (in Wei)\n    /// @param amortAttCost_    Amortized cost for attestation submission (in Wei)\n    /// @param etherPrice_      Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n    /// @param markup_          Markup for the message execution (in BWAD)\n    function encodeGasData(\n        Number gasPrice_,\n        Number dataPrice_,\n        Number execBuffer_,\n        Number amortAttCost_,\n        Number etherPrice_,\n        Number markup_\n    ) internal pure returns (GasData) {\n        // Number type wraps uint16, so could safely be casted to uint96\n        // forgefmt: disable-next-item\n        return GasData.wrap(\n            uint96(Number.unwrap(gasPrice_)) \u003c\u003c SHIFT_GAS_PRICE |\n            uint96(Number.unwrap(dataPrice_)) \u003c\u003c SHIFT_DATA_PRICE |\n            uint96(Number.unwrap(execBuffer_)) \u003c\u003c SHIFT_EXEC_BUFFER |\n            uint96(Number.unwrap(amortAttCost_)) \u003c\u003c SHIFT_AMORT_ATT_COST |\n            uint96(Number.unwrap(etherPrice_)) \u003c\u003c SHIFT_ETHER_PRICE |\n            uint96(Number.unwrap(markup_))\n        );\n    }\n\n    /// @notice Wraps padded uint256 value into GasData struct.\n    function wrapGasData(uint256 paddedGasData) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(paddedGasData));\n    }\n\n    /// @notice Returns the gas price, in Wei per gas unit.\n    function gasPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_GAS_PRICE));\n    }\n\n    /// @notice Returns the calldata price, in Wei per byte of content.\n    function dataPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_DATA_PRICE));\n    }\n\n    /// @notice Returns the tx fee safety buffer for message execution, in Wei.\n    function execBuffer(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_EXEC_BUFFER));\n    }\n\n    /// @notice Returns the amortized cost for attestation submission, in Wei.\n    function amortAttCost(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_AMORT_ATT_COST));\n    }\n\n    /// @notice Returns the ratio of Chain's Ether Price / Mainnet Ether Price, in BWAD math.\n    function etherPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_ETHER_PRICE));\n    }\n\n    /// @notice Returns the markup for the message execution, in BWAD math.\n    function markup(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data)));\n    }\n\n    // ════════════════════════════════════════════════ CHAIN DATA ═════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded ChainGas struct with the given fields.\n    /// @param gasData_ Chain's gas data\n    /// @param domain_  Chain's domain\n    function encodeChainGas(GasData gasData_, uint32 domain_) internal pure returns (ChainGas) {\n        // GasData type wraps uint96, so could safely be casted to uint128\n        return ChainGas.wrap(uint128(GasData.unwrap(gasData_)) \u003c\u003c SHIFT_GAS_DATA | uint128(domain_));\n    }\n\n    /// @notice Wraps padded uint256 value into ChainGas struct.\n    function wrapChainGas(uint256 paddedChainGas) internal pure returns (ChainGas) {\n        // Casting to uint128 will truncate the highest bits, which is the behavior we want\n        return ChainGas.wrap(uint128(paddedChainGas));\n    }\n\n    /// @notice Returns the chain's gas data.\n    function gasData(ChainGas data) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(ChainGas.unwrap(data) \u003e\u003e SHIFT_GAS_DATA));\n    }\n\n    /// @notice Returns the chain's domain.\n    function domain(ChainGas data) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(ChainGas.unwrap(data));\n    }\n\n    /// @notice Returns the hash for the list of ChainGas structs.\n    function snapGasHash(ChainGas[] memory snapGas) internal pure returns (bytes32 snapGasHash_) {\n        // Use assembly to calculate the hash of the array without copying it\n        // ChainGas takes a single word of storage, thus ChainGas[] is stored in the following way:\n        // 0x00: length of the array, in words\n        // 0x20: first ChainGas struct\n        // 0x40: second ChainGas struct\n        // And so on...\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Find the location where the array data starts, we add 0x20 to skip the length field\n            let loc := add(snapGas, 0x20)\n            // Load the length of the array (in words).\n            // Shifting left 5 bits is equivalent to multiplying by 32: this converts from words to bytes.\n            let len := shl(5, mload(snapGas))\n            // Calculate the hash of the array\n            snapGasHash_ := keccak256(loc, len)\n        }\n    }\n}\n\n// contracts/libs/stack/Header.sol\n\n/// Header is encoded data with \"general routing information\".\ntype Header is uint136;\n\nusing HeaderLib for Header global;\n\n/// Types of messages supported by Origin-Destination\n/// - Base: message sent by protocol user, contains tips\n/// - Manager: message sent between AgentManager contracts located on different chains, no tips\nenum MessageFlag {\n    Base,\n    Manager\n}\n\nusing HeaderLib for MessageFlag global;\n\n/// Library for formatting _the header part_ of _the messages used by Origin and Destination_.\n/// - Header represents general information for routing a Message for Origin and Destination.\n/// - Header occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n///\n/// # Header stack layout (from highest bits to lowest)\n///\n/// | Position   | Field            | Type   | Bytes | Description                             |\n/// | ---------- | ---------------- | ------ | ----- | --------------------------------------- |\n/// | (017..016] | flag             | uint8  | 1     | Flag specifying the type of message     |\n/// | (016..012] | origin           | uint32 | 4     | Domain where message originated         |\n/// | (012..008] | nonce            | uint32 | 4     | Message nonce on the origin domain      |\n/// | (008..004] | destination      | uint32 | 4     | Domain where message will be executed   |\n/// | (004..000] | optimisticPeriod | uint32 | 4     | Optimistic period that will be enforced |\nlibrary HeaderLib {\n    /// @dev Amount of bits to shift to flag field\n    uint136 private constant SHIFT_FLAG = 16 * 8;\n    /// @dev Amount of bits to shift to origin field\n    uint136 private constant SHIFT_ORIGIN = 12 * 8;\n    /// @dev Amount of bits to shift to nonce field\n    uint136 private constant SHIFT_NONCE = 8 * 8;\n    /// @dev Amount of bits to shift to destination field\n    uint136 private constant SHIFT_DESTINATION = 4 * 8;\n\n    /// @notice Returns an encoded header with provided fields\n    /// @param origin_              Domain of origin chain\n    /// @param nonce_               Message nonce on origin chain\n    /// @param destination_         Domain of destination chain\n    /// @param optimisticPeriod_    Optimistic period for message execution\n    function encodeHeader(\n        MessageFlag flag_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint32 destination_,\n        uint32 optimisticPeriod_\n    ) internal pure returns (Header) {\n        // All casts below are upcasts, so they are safe\n        // forgefmt: disable-next-item\n        return Header.wrap(\n            uint136(uint8(flag_)) \u003c\u003c SHIFT_FLAG |\n            uint136(origin_) \u003c\u003c SHIFT_ORIGIN |\n            uint136(nonce_) \u003c\u003c SHIFT_NONCE |\n            uint136(destination_) \u003c\u003c SHIFT_DESTINATION |\n            uint136(optimisticPeriod_)\n        );\n    }\n\n    /// @notice Checks that the header is a valid encoded header.\n    function isHeader(uint256 paddedHeader) internal pure returns (bool) {\n        // Check that flag is within range\n        return _flag(paddedHeader) \u003c= uint8(type(MessageFlag).max);\n    }\n\n    /// @notice Wraps the padded encoded request into a Header-typed value.\n    /// @dev The \"padded\" header is simply an encoded header casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded headers\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedHeader) internal pure returns (Header) {\n        // Check that flag is within range\n        if (!isHeader(paddedHeader)) revert FlagOutOfRange();\n        // Casting to uint136 will truncate the highest bits, which is the behavior we want\n        return Header.wrap(uint136(paddedHeader));\n    }\n\n    /// @notice Returns header's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Header header) internal pure returns (bytes32 hashedHeader) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store header in scratch space\n            mstore(0, header)\n            // Compute hash of header padded to 32 bytes\n            hashedHeader := keccak256(0, 32)\n        }\n    }\n\n    // ══════════════════════════════════════════════ HEADER SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns header's flag field\n    function flag(Header header) internal pure returns (MessageFlag) {\n        // We check that flag is within range when wrapping the header, so this cast is safe\n        return MessageFlag(_flag(Header.unwrap(header)));\n    }\n\n    /// @notice Returns header's origin field\n    function origin(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_ORIGIN);\n    }\n\n    /// @notice Returns header's nonce field\n    function nonce(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_NONCE);\n    }\n\n    /// @notice Returns header's destination field\n    function destination(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_DESTINATION);\n    }\n\n    /// @notice Returns header's optimistic seconds field\n    function optimisticPeriod(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns header's flag field without casting to MessageFlag\n    function _flag(uint256 paddedHeader) private pure returns (uint8) {\n        // Casting to uint8 will truncate the highest bits, which is the behavior we want\n        return uint8(paddedHeader \u003e\u003e SHIFT_FLAG);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n     * constructor.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall \u0026\u0026 _initialized \u003c 1) || (!AddressUpgradeable.isContract(address(this)) \u0026\u0026 _initialized == 1),\n            \"Initializable: contract is already initialized\"\n        );\n        _initialized = 1;\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: setting the version to 255 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing \u0026\u0026 _initialized \u003c version, \"Initializable: contract is already initialized\");\n        _initialized = version;\n        _initializing = true;\n        _;\n        _initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        require(_initializing, \"Initializable: contract is not initializing\");\n        _;\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized != type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint8) {\n        return _initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _initializing;\n    }\n}\n\n// contracts/interfaces/IAgentManager.sol\n\ninterface IAgentManager {\n    /**\n     * @notice Allows Inbox to open a Dispute between a Guard and a Notary, if they are both not in Dispute already.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Guard or Notary is already in Dispute.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Allows Inbox to slash an agent, if their fraud was proven.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Domain doesn't match the saved agent domain.\n     * @param domain    Domain where the Agent is active\n     * @param agent     Address of the Agent\n     * @param prover    Address that initially provided fraud proof\n     */\n    function slashAgent(uint32 domain, address agent, address prover) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest known root of the Agent Merkle Tree.\n     */\n    function agentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns the number of opened Disputes.\n     * @dev This includes the Disputes that have been resolved already.\n     */\n    function getDisputesAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns information about the dispute with the given index.\n     * @dev Will revert if dispute with given index hasn't been opened yet.\n     * @param index             Dispute index\n     * @return guard            Address of the Guard in the Dispute\n     * @return notary           Address of the Notary in the Dispute\n     * @return slashedAgent     Address of the Agent who was slashed when Dispute was resolved\n     * @return fraudProver      Address who provided fraud proof to resolve the Dispute\n     * @return reportPayload    Raw payload with report data that led to the Dispute\n     * @return reportSignature  Guard signature for the report payload\n     */\n    function getDispute(uint256 index)\n        external\n        view\n        returns (\n            address guard,\n            address notary,\n            address slashedAgent,\n            address fraudProver,\n            bytes memory reportPayload,\n            bytes memory reportSignature\n        );\n\n    /**\n     * @notice Returns the current Dispute status of a given agent. See Structures.sol for details.\n     * @dev Every returned value will be set to zero if agent was not slashed and is not in Dispute.\n     * `rival` and `disputePtr` will be set to zero if the agent was slashed without being in Dispute.\n     * @param agent         Agent address\n     * @return flag         Flag describing the current Dispute status for the agent: None/Pending/Slashed\n     * @return rival        Address of the rival agent in the Dispute\n     * @return fraudProver  Address who provided fraud proof to resolve the Dispute\n     * @return disputePtr   Index of the opened Dispute PLUS ONE. Zero if agent is not in Dispute.\n     */\n    function disputeStatus(address agent)\n        external\n        view\n        returns (DisputeFlag flag, address rival, address fraudProver, uint256 disputePtr);\n}\n\n// contracts/interfaces/IAgentSecured.sol\n\ninterface IAgentSecured {\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * between a Guard and a Notary has been opened.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * has been resolved due to one of the agents being slashed.\n     * \u003e `rivalIndex` will be ZERO, if the slashed agent was not in the Dispute.\n     * @param slashedIndex  Index of the slashed agent in the Agent Merkle Tree\n     * @param rivalIndex    Index of the their Dispute Rival in the Agent Merkle Tree\n     */\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the address of the local AgentManager contract, which is treated as\n     * the \"source of truth\" for agent statuses.\n     */\n    function agentManager() external view returns (address);\n\n    /**\n     * @notice Returns the address of the local Inbox contract, which is treated as\n     * the \"source of truth\" for agent-signed statements.\n     * @dev Inbox passes verified agent statements to `IAgentSecured` contract.\n     */\n    function inbox() external view returns (address);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns (flag, openedAt, resolvedAt) that describes the latest status of\n     * the latest dispute for an agent with a given index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param agentIndex    Agent index in the Agent Merkle Tree\n     * @return              Latest dispute status for the given agent: (flag, openedAt, resolvedAt)\n     */\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory);\n}\n\n// contracts/libs/memory/ByteString.sol\n\n/// @dev CallData is a memory view over the payload to be used for an external call, i.e.\n/// recipient.call(callData). Its length is always (4 + 32 * N) bytes:\n/// - First 4 bytes represent the function selector.\n/// - 32 * N bytes represent N words that function arguments occupy.\ntype CallData is uint256;\n\n/// @dev Attach library functions to CallData\nusing ByteString for CallData global;\n\n/// @dev Signature is a memory view over a \"65 bytes\" array representing a ECDSA signature.\ntype Signature is uint256;\n\n/// @dev Attach library functions to Signature\nusing ByteString for Signature global;\n\nlibrary ByteString {\n    using MemViewLib for bytes;\n\n    /**\n     * @dev non-compact ECDSA signatures are enforced as of OZ 4.7.3\n     *\n     *      Signature payload memory layout\n     * [000 .. 032) r   bytes32 32 bytes\n     * [032 .. 064) s   bytes32 32 bytes\n     * [064 .. 065) v   uint8    1 byte\n     */\n    uint256 internal constant SIGNATURE_LENGTH = 65;\n    uint256 private constant OFFSET_R = 0;\n    uint256 private constant OFFSET_S = 32;\n    uint256 private constant OFFSET_V = 64;\n\n    /**\n     * @dev Calldata memory layout\n     * [000 .. 004) selector    bytes4  4 bytes\n     *      Optional: N function arguments\n     * [004 .. 036) arg1        bytes32 32 bytes\n     *      ..\n     * [AAA .. END) argN        bytes32 32 bytes\n     */\n    uint256 internal constant SELECTOR_LENGTH = 4;\n    uint256 private constant OFFSET_SELECTOR = 0;\n    uint256 private constant OFFSET_ARGUMENTS = SELECTOR_LENGTH;\n\n    // ═════════════════════════════════════════════════ SIGNATURE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the signature payload from the given values.\n     * @dev Using ByteString.formatSignature({r: r, s: s, v: v}) will make sure\n     * that params are given in the right order.\n     */\n    function formatSignature(bytes32 r, bytes32 s, uint8 v) internal pure returns (bytes memory) {\n        return abi.encodePacked(r, s, v);\n    }\n\n    /**\n     * @notice Returns a Signature view over for the given payload.\n     * @dev Will revert if the payload is not a signature.\n     */\n    function castToSignature(bytes memory payload) internal pure returns (Signature) {\n        return castToSignature(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Signature view.\n     * @dev Will revert if the memory view is not over a signature.\n     */\n    function castToSignature(MemView memView) internal pure returns (Signature) {\n        if (!isSignature(memView)) revert UnformattedSignature();\n        return Signature.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a signature\n     */\n    function isSignature(MemView memView) internal pure returns (bool) {\n        return memView.len() == SIGNATURE_LENGTH;\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Signature signature) internal pure returns (MemView) {\n        return MemView.wrap(Signature.unwrap(signature));\n    }\n\n    // ═════════════════════════════════════════════ SIGNATURE SLICING ═════════════════════════════════════════════════\n\n    /// @notice Unpacks signature payload into (r, s, v) parameters.\n    /// @dev Make sure to verify signature length with isSignature() beforehand.\n    function toRSV(Signature signature) internal pure returns (bytes32 r, bytes32 s, uint8 v) {\n        // Get the underlying memory view\n        MemView memView = unwrap(signature);\n        r = memView.index({index_: OFFSET_R, bytes_: 32});\n        s = memView.index({index_: OFFSET_S, bytes_: 32});\n        // Can be safely casted to uint8, since we index a single byte\n        v = uint8(memView.indexUint({index_: OFFSET_V, bytes_: 1}));\n    }\n\n    // ═════════════════════════════════════════════════ CALLDATA ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the calldata with the modified arguments:\n     * the existing arguments are prepended with the arguments from the prefix.\n     * @dev Given:\n     *  - `calldata = abi.encodeWithSelector(foo.selector, d, e);`\n     *  - `prefix = abi.encode(a, b, c);`\n     *  - `a`, `b`, `c` are arguments of static type (i.e. not dynamically sized ones)\n     *      Then:\n     *  - Function will return abi.encodeWithSelector(foo.selector, a, c, c, d, e)\n     *  - Returned calldata will trigger `foo(a, b, c, d, e)` when used for a contract call.\n     * Note: for clarification as to what types are considered static, see\n     * https://docs.soliditylang.org/en/latest/abi-spec.html#formal-specification-of-the-encoding\n     * @param callData  Calldata that needs to be modified\n     * @param prefix    ABI-encoded arguments to use as the first arguments in the new calldata\n     * @return Modified calldata having prefix as the first arguments.\n     */\n    function addPrefix(CallData callData, bytes memory prefix) internal view returns (bytes memory) {\n        // Prefix should occupy a whole amount of words in memory\n        if (!_fullWords(prefix.length)) revert UnformattedCallDataPrefix();\n        MemView[] memory views = new MemView[](3);\n        // Use payload's function selector\n        views[0] = abi.encodePacked(callData.callSelector()).ref();\n        // Use prefix as the first arguments\n        views[1] = prefix.ref();\n        // Use payload's remaining arguments\n        views[2] = callData.arguments();\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a CallData view over for the given payload.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(bytes memory payload) internal pure returns (CallData) {\n        return castToCallData(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a CallData view.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(MemView memView) internal pure returns (CallData) {\n        if (!isCallData(memView)) revert UnformattedCallData();\n        return CallData.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a valid calldata, i.e.\n     * a function selector, followed by arbitrary amount of arguments.\n     */\n    function isCallData(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Calldata should at least have a function selector\n        if (length \u003c SELECTOR_LENGTH) return false;\n        // The remainder of the calldata should be exactly N memory words (N \u003e= 0)\n        return _fullWords(length - SELECTOR_LENGTH);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(CallData callData) internal pure returns (MemView) {\n        return MemView.wrap(CallData.unwrap(callData));\n    }\n\n    /// @notice Returns callData's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(CallData callData) internal pure returns (bytes32) {\n        return callData.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ CALLDATA SLICING ══════════════════════════════════════════════════\n\n    /**\n     * @notice Returns amount of memory words (32 byte chunks) the function arguments\n     * occupy in the calldata.\n     * @dev This might differ from amount of arguments supplied, if any of the arguments\n     * occupies more than one memory slot. It is true, however, that argument part of the payload\n     * occupies exactly N words, even for dynamic types like `bytes`\n     */\n    function argumentWords(CallData callData) internal pure returns (uint256) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        // Equivalent of (length - SELECTOR_LENGTH) / 32\n        return (memView.len() - SELECTOR_LENGTH) \u003e\u003e 5;\n    }\n\n    /// @notice Returns selector for the provided calldata.\n    function callSelector(CallData callData) internal pure returns (bytes4) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return bytes4(memView.index({index_: OFFSET_SELECTOR, bytes_: SELECTOR_LENGTH}));\n    }\n\n    /// @notice Returns abi encoded arguments for the provided calldata.\n    function arguments(CallData callData) internal pure returns (MemView) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return memView.sliceFrom({index_: OFFSET_ARGUMENTS});\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if length is full amount of memory words (32 bytes).\n    function _fullWords(uint256 length) internal pure returns (bool) {\n        // The equivalent of length % 32 == 0\n        return length \u0026 31 == 0;\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n    function __Context_init() internal onlyInitializing {\n    }\n\n    function __Context_init_unchained() internal onlyInitializing {\n    }\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[50] private __gap;\n}\n\n// contracts/libs/merkle/MerkleTree.sol\n\n/// `BaseTree` is a struct representing incremental merkle tree.\n/// - Contains only the current branch.\n/// - The number of inserted leaves is stored externally, and is later supplied for tree operations.\n/// - Has a fixed height of `ORIGIN_TREE_HEIGHT`.\n/// - Can store up to `2 ** ORIGIN_TREE_HEIGHT - 1` leaves.\n/// \u003e Note: the hash function for the tree `H(x, y)` is defined as:\n/// \u003e - `H(0,0) = 0`\n/// \u003e - `H(x,y) = keccak256(x, y), when (x != 0 || y != 0)`\n/// ## Invariant for leafs\n/// - The leftmost empty leaf has `index == count`, where `count` is the amount of the inserted leafs so far.\n/// - Value for any empty leaf or node is bytes32(0).\n/// ## Invariant for current branch\n/// `branch[i]` is always the value of a node on the i-th level.\n/// Levels are numbered from leafs to root: `0 .. ORIGIN_TREE_HEIGHT`.\n/// `branch[i]` stores the value for the node, such that:\n//  - The node is a \"left child\" (e.g. has an even index).\n/// - The node must have two non-empty children.\n/// - Out of all level's \"left child\" nodes with \"non-empty children\",\n/// the one with the biggest index (the rightmost one) is stored as `branch[i]`.\n/// \u003e __`branch` could be used to form a proof of inclusion for the first empty leaf (`index == count`).__\n/// _Here is how:_\n/// - Let's walk along the path from the \"first empty leaf\" to the root.\n/// - i-th bit of the \"first empty leaf\" index (which is equal to `count`) determines if the path's node\n/// for this i-th level is a \"left child\" or a \"right child\".\n/// - i-th bit in `count` is 0 → we are the left child on this level → sibling is the right child\n/// that does not exist yet → `proof[i] = bytes32(0)`.\n/// - i-th bit in `count` is 1 → we are the right child on this level → sibling is the left child\n/// sibling is the rightmost \"left child\" node on the level → `proof[i] = branch[i]`.\n/// \u003e Therefore `proof[i] = (count \u0026 (1 \u003c\u003c i)) == 0 ? bytes32(0) : branch[i])`\nstruct BaseTree {\n    bytes32[ORIGIN_TREE_HEIGHT] branch;\n}\n\nusing MerkleTree for BaseTree global;\n\n/// `HistoricalTree` is an incremental merkle tree keeping track of its historical merkle roots.\n/// \u003e - `roots[N]` is the root of the tree after `N` leafs were inserted\n/// \u003e - `roots[0] == bytes32(0)`\n/// @param tree     Incremental merkle tree\n/// @param roots    Historical merkle roots of the tree\nstruct HistoricalTree {\n    BaseTree tree;\n    bytes32[] roots;\n}\n\nusing MerkleTree for HistoricalTree global;\n\n/// `DynamicTree` is a struct representing a Merkle Tree with `2**AGENT_TREE_HEIGHT` leaves.\n/// - A single operation is available: update value for leaf with an arbitrary index (which might be a non-empty leaf).\n/// - This is done by requesting the proof of inclusion for the old value, which is used to both\n/// verify the old value, and calculate the new root.\n/// \u003e Based on Original idea from [ER forum post](https://ethresear.ch/t/efficient-on-chain-dynamic-merkle-tree/11054).\nstruct DynamicTree {\n    bytes32 root;\n}\n\nusing MerkleTree for DynamicTree global;\n\n/// MerkleTree is work based on Nomad's Merkle.sol, which is used under MIT OR Apache-2.0\n/// [link](https://github.com/nomad-xyz/monorepo/blob/main/packages/contracts-core/contracts/libs/Merkle.sol).\n/// With the following changes:\n/// - Adapted for Solidity 0.8.x.\n/// - Amount of tree leaves stored externally.\n/// - Added thorough documentation.\n/// - `H(0,0) = 0` optimization from [ER forum post](https://ethresear.ch/t/optimizing-sparse-merkle-trees/3751/6).\n/// \u003e Nomad's Merkle.sol is work based on eth2 deposit contract, which is used under CC0-1.0\n///[link](https://github.com/ethereum/deposit_contract/blob/dev/deposit_contract/contracts/validator_registration.v.py).\n/// With the following changes:\n/// \u003e - Implemented in Solidity 0.7.6 (eth2 deposit contract implemented in Vyper).\n/// \u003e - `H() = keccak256()` is used as the hashing function instead of `sha256()`.\nlibrary MerkleTree {\n    /// @dev For root calculation we need at least one empty leaf, thus the minus one in the formula.\n    uint256 internal constant MAX_LEAVES = 2 ** ORIGIN_TREE_HEIGHT - 1;\n\n    // ═════════════════════════════════════════════════ BASE TREE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Inserts `node` into merkle tree\n     * @dev Reverts if tree is full\n     * @param newCount  Amount of inserted leaves in the tree after the insertion (i.e. current + 1)\n     * @param node      Element to insert into tree\n     */\n    function insertBase(BaseTree storage tree, uint256 newCount, bytes32 node) internal {\n        if (newCount \u003e MAX_LEAVES) revert MerkleTreeFull();\n        // We go up the tree following the branch from the empty leaf AFTER the just inserted one.\n        // We stop when we find the first \"right child\" node.\n        // Its sibling is now the rightmost \"left child\" node that has two non-empty children.\n        // Therefore we need to update `tree.branch` value on this level.\n        // One could see that `tree.branch` value on lower and higher levels remain unchanged.\n\n        // Loop invariant: `node` is the current level's value for the branch from JUST INSERTED leaf\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            if ((newCount \u0026 1) == 1) {\n                // Found the first \"right child\" node on the branch from EMPTY leaf\n                // `node` is the value for node on branch from JUST INSERTED leaf\n                // Which in this case is the \"left child\".\n                // We update tree.branch and exit\n                tree.branch[i] = node;\n                return;\n            }\n            // On the branch from EMPTY leaf this is still a \"left child\".\n            // Meaning on branch from JUST INSERTED leaf, `node` is a right child.\n            // We compute value for `node` parent using `tree.branch` invariant:\n            // This is the rightmost \"left child\" node, which would be sibling of `node`.\n            node = MerkleMath.getParent(tree.branch[i], node);\n            // Get the parent index, and go to the next tree level\n            newCount \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n        // As the loop should always end prematurely with the `return` statement,\n        // this code should be unreachable. We assert `false` just to be safe.\n        assert(false);\n    }\n\n    /**\n     * @notice Calculates and returns current root of the merkle tree.\n     * @param count     Current amount of inserted leaves in the tree\n     * @return current  Calculated root of `tree`\n     */\n    function rootBase(BaseTree storage tree, uint256 count) internal view returns (bytes32 current) {\n        // To calculate the root we follow the branch of first EMPTY leaf (index == count)\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            // Check if we are the left or the right child on the current level\n            if ((count \u0026 1) == 1) {\n                // We are the right child. Our sibling is the \"rightmost\" \"left-child\" node\n                // that has two non-empty children → sibling is `tree.branch[i]`\n                current = MerkleMath.getParent(tree.branch[i], current);\n            } else {\n                // We are the left child. Our sibling does not exist yet → sibling is EMPTY\n                current = MerkleMath.getParent(current, bytes32(0));\n            }\n            // Get the parent index, and go to the next tree level\n            count \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    // ══════════════════════════════════════════════ HISTORICAL TREE ══════════════════════════════════════════════════\n\n    /// @notice Initializes the historical roots for the tree by inserting an empty root.\n    // solhint-disable-next-line ordering\n    function initializeRoots(HistoricalTree storage tree) internal returns (bytes32 savedRoot) {\n        // This should only be called once, when the contract is initialized\n        assert(tree.roots.length == 0);\n        // Save root for empty merkle tree: bytes32(0)\n        tree.roots.push(savedRoot);\n    }\n\n    /// @notice Inserts a new leaf into the merkle tree.\n    /// @dev Reverts if tree is full.\n    /// @param node         Element to insert into tree\n    /// @return newRoot     Merkle root after the leaf was inserted\n    function insert(HistoricalTree storage tree, bytes32 node) internal returns (bytes32 newRoot) {\n        // Tree count after the new leaf will be inserted (we store roots[0] as root of empty tree)\n        uint256 newCount = tree.roots.length;\n        tree.tree.insertBase(newCount, node);\n        // Save the new root\n        newRoot = tree.tree.rootBase(newCount);\n        tree.roots.push(newRoot);\n    }\n\n    /// @notice Returns the historical root of the merkle tree.\n    /// @dev Reverts if not enough leafs have been inserted.\n    /// @param count            Amount of leafs in the tree at some point of time\n    /// @return historicalRoot  Merkle root after `count` leafs were inserted\n    function root(HistoricalTree storage tree, uint256 count) internal view returns (bytes32 historicalRoot) {\n        if (count \u003e= tree.roots.length) revert NotEnoughLeafs();\n        return tree.roots[count];\n    }\n\n    // ═══════════════════════════════════════════════ DYNAMIC TREE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Updates the value for the leaf with the given index in the Dynamic Merkle Tree.\n     * @dev Will revert if incorrect proof of inclusion for old value is supplied.\n     * @param tree          Dynamic merkle tree\n     * @param index         Index of the leaf to update\n     * @param oldValue      Previous value of the leaf\n     * @param branch        Proof of inclusion of previous value into the tree\n     * @param newValue      New leaf value to assign\n     * @return newRoot      New value for the Merkle Root after the leaf is updated\n     */\n    function update(\n        DynamicTree storage tree,\n        uint256 index,\n        bytes32 oldValue,\n        bytes32[] memory branch,\n        bytes32 newValue\n    ) internal returns (bytes32 newRoot) {\n        // Check that the old value + proof result in a correct root\n        if (MerkleMath.proofRoot(index, oldValue, branch, AGENT_TREE_HEIGHT) != tree.root) {\n            revert LeafNotProven();\n        }\n        // New root is new value + the same proof (values for sibling nodes are not updated)\n        newRoot = MerkleMath.proofRoot(index, newValue, branch, AGENT_TREE_HEIGHT);\n        // Write the new root\n        tree.root = newRoot;\n    }\n}\n\n// contracts/libs/stack/Tips.sol\n\n/// Tips is encoded data with \"tips paid for sending a base message\".\n/// Note: even though uint256 is also an underlying type for MemView, Tips is stored ON STACK.\ntype Tips is uint256;\n\nusing TipsLib for Tips global;\n\n/// # Tips\n/// Library for formatting _the tips part_ of _the base messages_.\n///\n/// ## How the tips are awarded\n/// Tips are paid for sending a base message, and are split across all the agents that\n/// made the message execution on destination chain possible.\n/// ### Summit tips\n/// Split between:\n///     - Guard posting a snapshot with state ST_G for the origin chain.\n///     - Notary posting a snapshot SN_N using ST_G. This creates attestation A.\n///     - Notary posting a message receipt after it is executed on destination chain.\n/// ### Attestation tips\n/// Paid to:\n///     - Notary posting attestation A to destination chain.\n/// ### Execution tips\n/// Paid to:\n///     - First executor performing a valid execution attempt (correct proofs, optimistic period over),\n///      using attestation A to prove message inclusion on origin chain, whether the recipient reverted or not.\n/// ### Delivery tips.\n/// Paid to:\n///     - Executor who successfully executed the message on destination chain.\n///\n/// ## Tips encoding\n/// - Tips occupy a single storage word, and thus are stored on stack instead of being stored in memory.\n/// - The actual tip values should be determined by multiplying stored values by divided by TIPS_MULTIPLIER=2**32.\n/// - Tips are packed into a single word of storage, while allowing real values up to ~8*10**28 for every tip category.\n/// \u003e The only downside is that the \"real tip values\" are now multiplies of ~4*10**9, which should be fine even for\n/// the chains with the most expensive gas currency.\n/// # Tips stack layout (from highest bits to lowest)\n///\n/// | Position   | Field          | Type   | Bytes | Description                                                |\n/// | ---------- | -------------- | ------ | ----- | ---------------------------------------------------------- |\n/// | (032..024] | summitTip      | uint64 | 8     | Tip for agents interacting with Summit contract            |\n/// | (024..016] | attestationTip | uint64 | 8     | Tip for Notary posting attestation to Destination contract |\n/// | (016..008] | executionTip   | uint64 | 8     | Tip for valid execution attempt on destination chain       |\n/// | (008..000] | deliveryTip    | uint64 | 8     | Tip for successful message delivery on destination chain   |\n\nlibrary TipsLib {\n    using SafeCast for uint256;\n\n    /// @dev Amount of bits to shift to summitTip field\n    uint256 private constant SHIFT_SUMMIT_TIP = 24 * 8;\n    /// @dev Amount of bits to shift to attestationTip field\n    uint256 private constant SHIFT_ATTESTATION_TIP = 16 * 8;\n    /// @dev Amount of bits to shift to executionTip field\n    uint256 private constant SHIFT_EXECUTION_TIP = 8 * 8;\n\n    // ═══════════════════════════════════════════════════ TIPS ════════════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips with the given fields\n    /// @param summitTip_        Tip for agents interacting with Summit contract, divided by TIPS_MULTIPLIER\n    /// @param attestationTip_   Tip for Notary posting attestation to Destination contract, divided by TIPS_MULTIPLIER\n    /// @param executionTip_     Tip for valid execution attempt on destination chain, divided by TIPS_MULTIPLIER\n    /// @param deliveryTip_      Tip for successful message delivery on destination chain, divided by TIPS_MULTIPLIER\n    function encodeTips(uint64 summitTip_, uint64 attestationTip_, uint64 executionTip_, uint64 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // forgefmt: disable-next-item\n        return Tips.wrap(\n            uint256(summitTip_) \u003c\u003c SHIFT_SUMMIT_TIP |\n            uint256(attestationTip_) \u003c\u003c SHIFT_ATTESTATION_TIP |\n            uint256(executionTip_) \u003c\u003c SHIFT_EXECUTION_TIP |\n            uint256(deliveryTip_)\n        );\n    }\n\n    /// @notice Convenience function to encode tips with uint256 values.\n    function encodeTips256(uint256 summitTip_, uint256 attestationTip_, uint256 executionTip_, uint256 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // In practice, the tips amounts are not supposed to be higher than 2**96, and with 32 bits of granularity\n        // using uint64 is enough to store the values. However, we still check for overflow just in case.\n        // TODO: consider using Number type to store the tips values.\n        return encodeTips({\n            summitTip_: (summitTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            attestationTip_: (attestationTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            executionTip_: (executionTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            deliveryTip_: (deliveryTip_ \u003e\u003e TIPS_GRANULARITY).toUint64()\n        });\n    }\n\n    /// @notice Wraps the padded encoded tips into a Tips-typed value.\n    /// @dev There is no actual padding here, as the underlying type is already uint256,\n    /// but we include this function for consistency and to be future-proof, if tips will eventually use anything\n    /// smaller than uint256.\n    function wrapPadded(uint256 paddedTips) internal pure returns (Tips) {\n        return Tips.wrap(paddedTips);\n    }\n\n    /**\n     * @notice Returns a formatted Tips payload specifying empty tips.\n     * @return Formatted tips\n     */\n    function emptyTips() internal pure returns (Tips) {\n        return Tips.wrap(0);\n    }\n\n    /// @notice Returns tips's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Tips tips) internal pure returns (bytes32 hashedTips) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store tips in scratch space\n            mstore(0, tips)\n            // Compute hash of tips padded to 32 bytes\n            hashedTips := keccak256(0, 32)\n        }\n    }\n\n    // ═══════════════════════════════════════════════ TIPS SLICING ════════════════════════════════════════════════════\n\n    /// @notice Returns summitTip field\n    function summitTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_SUMMIT_TIP);\n    }\n\n    /// @notice Returns attestationTip field\n    function attestationTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_ATTESTATION_TIP);\n    }\n\n    /// @notice Returns executionTip field\n    function executionTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_EXECUTION_TIP);\n    }\n\n    /// @notice Returns deliveryTip field\n    function deliveryTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips));\n    }\n\n    // ════════════════════════════════════════════════ TIPS VALUE ═════════════════════════════════════════════════════\n\n    /// @notice Returns total value of the tips payload.\n    /// This is the sum of the encoded values, scaled up by TIPS_MULTIPLIER\n    function value(Tips tips) internal pure returns (uint256 value_) {\n        value_ = uint256(tips.summitTip()) + tips.attestationTip() + tips.executionTip() + tips.deliveryTip();\n        value_ \u003c\u003c= TIPS_GRANULARITY;\n    }\n\n    /// @notice Increases the delivery tip to match the new value.\n    function matchValue(Tips tips, uint256 newValue) internal pure returns (Tips newTips) {\n        uint256 oldValue = tips.value();\n        if (newValue \u003c oldValue) revert TipsValueTooLow();\n        // We want to increase the delivery tip, while keeping the other tips the same\n        unchecked {\n            uint256 delta = (newValue - oldValue) \u003e\u003e TIPS_GRANULARITY;\n            // `delta` fits into uint224, as TIPS_GRANULARITY is 32, so this never overflows uint256.\n            // In practice, this will never overflow uint64 as well, but we still check it just in case.\n            if (delta + tips.deliveryTip() \u003e type(uint64).max) revert TipsOverflow();\n            // Delivery tips occupy lowest 8 bytes, so we can just add delta to the tips value\n            // to effectively increase the delivery tip (knowing that delta fits into uint64).\n            newTips = Tips.wrap(Tips.unwrap(tips) + delta);\n        }\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    function __Ownable_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable_init_unchained() internal onlyInitializing {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n    function __Ownable2Step_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable2Step_init_unchained() internal onlyInitializing {\n    }\n    address private _pendingOwner;\n\n    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Returns the address of the pending owner.\n     */\n    function pendingOwner() public view virtual returns (address) {\n        return _pendingOwner;\n    }\n\n    /**\n     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual override onlyOwner {\n        _pendingOwner = newOwner;\n        emit OwnershipTransferStarted(owner(), newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual override {\n        delete _pendingOwner;\n        super._transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev The new owner accepts the ownership transfer.\n     */\n    function acceptOwnership() public virtual {\n        address sender = _msgSender();\n        require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n        _transferOwnership(sender);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// contracts/libs/memory/State.sol\n\n/// State is a memory view over a formatted state payload.\ntype State is uint256;\n\nusing StateLib for State global;\n\n/// # State\n/// State structure represents the state of Origin contract at some point of time.\n/// - State is structured in a way to track the updates of the Origin Merkle Tree.\n/// - State includes root of the Origin Merkle Tree, origin domain and some additional metadata.\n/// ## Origin Merkle Tree\n/// Hash of every sent message is inserted in the Origin Merkle Tree, which changes\n/// the value of Origin Merkle Root (which is the root for the mentioned tree).\n/// - Origin has a single Merkle Tree for all messages, regardless of their destination domain.\n/// - This leads to Origin state being updated if and only if a message was sent in a block.\n/// - Origin contract is a \"source of truth\" for states: a state is considered \"valid\" in its Origin,\n/// if it matches the state of the Origin contract after the N-th (nonce) message was sent.\n///\n/// # Memory layout of State fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                    |\n/// | ---------- | ----------- | ------- | ----- | ------------------------------ |\n/// | [000..032) | root        | bytes32 | 32    | Root of the Origin Merkle Tree |\n/// | [032..036) | origin      | uint32  | 4     | Domain where Origin is located |\n/// | [036..040) | nonce       | uint32  | 4     | Amount of sent messages        |\n/// | [040..045) | blockNumber | uint40  | 5     | Block of last sent message     |\n/// | [045..050) | timestamp   | uint40  | 5     | Time of last sent message      |\n/// | [050..062) | gasData     | uint96  | 12    | Gas data for the chain         |\n///\n/// @dev State could be used to form a Snapshot to be signed by a Guard or a Notary.\nlibrary StateLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_ROOT = 0;\n    uint256 private constant OFFSET_ORIGIN = 32;\n    uint256 private constant OFFSET_NONCE = 36;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 40;\n    uint256 private constant OFFSET_TIMESTAMP = 45;\n    uint256 private constant OFFSET_GAS_DATA = 50;\n\n    // ═══════════════════════════════════════════════════ STATE ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted State payload with provided fields\n     * @param root_         New merkle root\n     * @param origin_       Domain of Origin's chain\n     * @param nonce_        Nonce of the merkle root\n     * @param blockNumber_  Block number when root was saved in Origin\n     * @param timestamp_    Block timestamp when root was saved in Origin\n     * @param gasData_      Gas data for the chain\n     * @return Formatted state\n     */\n    function formatState(\n        bytes32 root_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_,\n        GasData gasData_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(root_, origin_, nonce_, blockNumber_, timestamp_, gasData_);\n    }\n\n    /**\n     * @notice Returns a State view over the given payload.\n     * @dev Will revert if the payload is not a state.\n     */\n    function castToState(bytes memory payload) internal pure returns (State) {\n        return castToState(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a State view.\n     * @dev Will revert if the memory view is not over a state.\n     */\n    function castToState(MemView memView) internal pure returns (State) {\n        if (!isState(memView)) revert UnformattedState();\n        return State.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted State.\n    function isState(MemView memView) internal pure returns (bool) {\n        return memView.len() == STATE_LENGTH;\n    }\n\n    /// @notice Returns the hash of a State, that could be later signed by a Guard to signal\n    /// that the state is invalid.\n    function hashInvalid(State state) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(stateInvalidSalt, keccak(state))\n        return state.unwrap().keccakSalted(STATE_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(State state) internal pure returns (MemView) {\n        return MemView.wrap(State.unwrap(state));\n    }\n\n    /// @notice Compares two State structures.\n    function equals(State a, State b) internal pure returns (bool) {\n        // Length of a State payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═══════════════════════════════════════════════ STATE HASHING ═══════════════════════════════════════════════════\n\n    /// @notice Returns the hash of the State.\n    /// @dev We are using the Merkle Root of a tree with two leafs (see below) as state hash.\n    function leaf(State state) internal pure returns (bytes32) {\n        (bytes32 leftLeaf_, bytes32 rightLeaf_) = state.subLeafs();\n        // Final hash is the parent of these leafs\n        return keccak256(bytes.concat(leftLeaf_, rightLeaf_));\n    }\n\n    /// @notice Returns \"sub-leafs\" of the State. Hash of these \"sub leafs\" is going to be used\n    /// as a \"state leaf\" in the \"Snapshot Merkle Tree\".\n    /// This enables proving that leftLeaf = (root, origin) was a part of the \"Snapshot Merkle Tree\",\n    /// by combining `rightLeaf` with the remainder of the \"Snapshot Merkle Proof\".\n    function subLeafs(State state) internal pure returns (bytes32 leftLeaf_, bytes32 rightLeaf_) {\n        MemView memView = state.unwrap();\n        // Left leaf is (root, origin)\n        leftLeaf_ = memView.prefix({len_: OFFSET_NONCE}).keccak();\n        // Right leaf is (metadata), or (nonce, blockNumber, timestamp)\n        rightLeaf_ = memView.sliceFrom({index_: OFFSET_NONCE}).keccak();\n    }\n\n    /// @notice Returns the left \"sub-leaf\" of the State.\n    function leftLeaf(bytes32 root_, uint32 origin_) internal pure returns (bytes32) {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(root_, origin_));\n    }\n\n    /// @notice Returns the right \"sub-leaf\" of the State.\n    function rightLeaf(uint32 nonce_, uint40 blockNumber_, uint40 timestamp_, GasData gasData_)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(nonce_, blockNumber_, timestamp_, gasData_));\n    }\n\n    // ═══════════════════════════════════════════════ STATE SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns a historical Merkle root from the Origin contract.\n    function root(State state) internal pure returns (bytes32) {\n        return state.unwrap().index({index_: OFFSET_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns domain of chain where the Origin contract is deployed.\n    function origin(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns nonce of Origin contract at the time, when `root` was the Merkle root.\n    function nonce(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when `root` was saved in Origin.\n    function blockNumber(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when `root` was saved in Origin.\n    /// @dev This is the timestamp according to the origin chain.\n    function timestamp(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n\n    /// @notice Returns gas data for the chain.\n    function gasData(State state) internal pure returns (GasData) {\n        return GasDataLib.wrapGasData(state.unwrap().indexUint({index_: OFFSET_GAS_DATA, bytes_: GAS_DATA_LENGTH}));\n    }\n}\n\n// contracts/libs/memory/BaseMessage.sol\n\n/// BaseMessage is a memory view over the base message supported by Origin-Destination\ntype BaseMessage is uint256;\n\nusing BaseMessageLib for BaseMessage global;\n\n/// BaseMessage structure represents a base message sent via the Origin-Destination contracts.\n/// - It only contains data relevant to the base message, the rest of data is encoded in the message header.\n/// - `sender` and `recipient` for EVM chains are EVM addresses casted to bytes32, while preserving left-alignment.\n/// - `tips` and `request` parameters are specified by a message sender\n/// \u003e Origin will calculate minimum tips for given request and content length, and will reject messages with tips\n/// lower than that.\n///\n/// # Memory layout of BaseMessage fields\n///\n/// | Position   | Field     | Type    | Bytes | Description                            |\n/// | ---------- | --------- | ------- | ----- | -------------------------------------- |\n/// | [000..032) | tips      | uint256 | 32    | Encoded tips paid on origin chain      |\n/// | [032..064) | sender    | bytes32 | 32    | Sender address on origin chain         |\n/// | [064..096) | recipient | bytes32 | 32    | Recipient address on destination chain |\n/// | [096..116) | request   | uint160 | 20    | Encoded request for message execution  |\n/// | [104..AAA) | content   | bytes   | ??    | Content to be passed to recipient      |\nlibrary BaseMessageLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_TIPS = 0;\n    uint256 private constant OFFSET_SENDER = 32;\n    uint256 private constant OFFSET_RECIPIENT = 64;\n    uint256 private constant OFFSET_REQUEST = OFFSET_RECIPIENT + TIPS_LENGTH;\n    uint256 private constant OFFSET_CONTENT = OFFSET_REQUEST + REQUEST_LENGTH;\n\n    // ═══════════════════════════════════════════════ BASE MESSAGE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted BaseMessage payload with provided fields.\n     * @param tips_         Encoded tips information\n     * @param sender_       Sender address on origin chain\n     * @param recipient_    Recipient address on destination chain\n     * @param request_      Encoded request for message execution\n     * @param content_      Raw content to be passed to recipient on destination chain\n     * @return Formatted base message\n     */\n    function formatBaseMessage(Tips tips_, bytes32 sender_, bytes32 recipient_, Request request_, bytes memory content_)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return abi.encodePacked(tips_, sender_, recipient_, request_, content_);\n    }\n\n    /**\n     * @notice Returns a BaseMessage view over the given payload.\n     * @dev Will revert if the payload is not a base message.\n     */\n    function castToBaseMessage(bytes memory payload) internal pure returns (BaseMessage) {\n        return castToBaseMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a BaseMessage view.\n     * @dev Will revert if the memory view is not over a base message payload.\n     */\n    function castToBaseMessage(MemView memView) internal pure returns (BaseMessage) {\n        if (!isBaseMessage(memView)) revert UnformattedBaseMessage();\n        return BaseMessage.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted BaseMessage.\n    function isBaseMessage(MemView memView) internal pure returns (bool) {\n        // Check if sender, recipient, tips fields exist\n        return (memView.len() \u003e= OFFSET_CONTENT);\n        // Content could be empty, so we don't check that\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(BaseMessage baseMessage) internal pure returns (MemView) {\n        return MemView.wrap(BaseMessage.unwrap(baseMessage));\n    }\n\n    /// @notice Returns baseMessage's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        // We hash \"tips\" and \"everything but tips\" to make tips proofs easier to verify\n        return MerkleMath.getParent(baseMessage.tips().leaf(), baseMessage.bodyLeaf());\n    }\n\n    /// @notice Returns hash for the \"everything but tips\" part of the base message.\n    function bodyLeaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_SENDER}).keccak();\n    }\n\n    // ═══════════════════════════════════════════ BASE MESSAGE SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips paid on origin chain.\n    function tips(BaseMessage baseMessage) internal pure returns (Tips) {\n        return TipsLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_TIPS, bytes_: TIPS_LENGTH})));\n    }\n\n    /// @notice Returns sender address on origin chain.\n    function sender(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_SENDER, bytes_: 32});\n    }\n\n    /// @notice Returns recipient address on destination chain.\n    function recipient(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_RECIPIENT, bytes_: 32});\n    }\n\n    /// @notice Returns an encoded request for message execution on destination chain.\n    function request(BaseMessage baseMessage) internal pure returns (Request) {\n        return RequestLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_REQUEST, bytes_: REQUEST_LENGTH})));\n    }\n\n    /// @notice Returns an untyped memory view over the content to be passed to recipient.\n    function content(BaseMessage baseMessage) internal pure returns (MemView) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_CONTENT});\n    }\n}\n\n// contracts/base/MessagingBase.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for all messaging contracts.\n * - Provides context on the local chain's domain.\n * - Provides ownership functionality.\n * - Will be providing pausing functionality when it is implemented.\n */\nabstract contract MessagingBase is MultiCallable, Versioned, Ownable2StepUpgradeable {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @notice Domain of the local chain, set once upon contract creation\n    uint32 public immutable localDomain;\n    // @notice Domain of the Synapse chain, set once upon contract creation\n    uint32 public immutable synapseDomain;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev gap for upgrade safety\n    uint256[50] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    constructor(string memory version_, uint32 synapseDomain_) Versioned(version_) {\n        localDomain = ChainContext.chainId();\n        synapseDomain = synapseDomain_;\n    }\n\n    // TODO: Implement pausing\n\n    /**\n     * @dev Should be impossible to renounce ownership;\n     * we override OpenZeppelin OwnableUpgradeable's\n     * implementation of renounceOwnership to make it a no-op\n     */\n    function renounceOwnership() public override onlyOwner {} //solhint-disable-line no-empty-blocks\n}\n\n// contracts/libs/memory/Message.sol\n\n/// Message is a memory over over a formatted message payload.\ntype Message is uint256;\n\nusing MessageLib for Message global;\n\n/// Library for formatting the various messages supported by Origin and Destination.\n///\n/// # Message memory layout\n///\n/// | Position   | Field  | Type    | Bytes | Description                                             |\n/// | ---------- | ------ | ------- | ----- | ------------------------------------------------------- |\n/// | [000..017) | header | uint136 | 17    | Encoded general routing information for the message     |\n/// | [017..AAA) | body   | bytes   | ??    | Formatted payload (according to flag) with message body |\nlibrary MessageLib {\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MemViewLib for bytes;\n    using HeaderLib for MemView;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_HEADER = 0;\n    uint256 private constant OFFSET_BODY = OFFSET_HEADER + HEADER_LENGTH;\n\n    // ══════════════════════════════════════════════════ MESSAGE ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns formatted message with provided fields.\n     * @param header_   Encoded general routing information for the message\n     * @param body_     Formatted payload (according to flag) with message body\n     * @return Formatted message\n     */\n    function formatMessage(Header header_, bytes memory body_) internal pure returns (bytes memory) {\n        return abi.encodePacked(header_, body_);\n    }\n\n    /**\n     * @notice Returns a Message view over for the given payload.\n     * @dev Will revert if the payload is not a message payload.\n     */\n    function castToMessage(bytes memory payload) internal pure returns (Message) {\n        return castToMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Message view.\n     * @dev Will revert if the memory view is not over a message payload.\n     */\n    function castToMessage(MemView memView) internal pure returns (Message) {\n        if (!isMessage(memView)) revert UnformattedMessage();\n        return Message.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Message.\n     */\n    function isMessage(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Check if headers exist in the payload\n        if (length \u003c OFFSET_BODY) return false;\n        // Check that Header is valid\n        uint256 paddedHeader = _header(memView);\n        if (!HeaderLib.isHeader(paddedHeader)) return false;\n        // Check that body is formatted according to the flag\n        // Only Base/Manager message flags exist\n        if (HeaderLib.wrapPadded(paddedHeader).flag() == MessageFlag.Base) {\n            // Check if body is a formatted base message\n            return _body(memView).isBaseMessage();\n        } else {\n            // Check if body is a formatted calldata for AgentManager call\n            return _body(memView).isCallData();\n        }\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Message message) internal pure returns (MemView) {\n        return MemView.wrap(Message.unwrap(message));\n    }\n\n    /// @notice Returns message's hash: a leaf to be inserted in the Merkle tree.\n    function leaf(Message message) internal pure returns (bytes32) {\n        // We hash header and body separately to make message proofs easier to verify\n        Header header_ = message.header();\n        // Only Base/Manager message flags exist\n        if (header_.flag() == MessageFlag.Base) {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToBaseMessage().leaf());\n        } else {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToCallData().leaf());\n        }\n    }\n\n    // ══════════════════════════════════════════════ MESSAGE SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns message's encoded header field.\n    function header(Message message) internal pure returns (Header) {\n        return HeaderLib.wrapPadded((message.unwrap().indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH})));\n    }\n\n    /// @notice Returns message's body field as an untyped memory view.\n    function body(Message message) internal pure returns (MemView) {\n        MemView memView = message.unwrap();\n        return _body(memView);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns message's padded header without checking that it is a valid header.\n    function _header(MemView memView) private pure returns (uint256) {\n        return memView.indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH});\n    }\n\n    /// @dev Returns an untyped memory view over the body field without checking\n    /// if the whole payload or the body are properly formatted.\n    function _body(MemView memView) private pure returns (MemView) {\n        return memView.sliceFrom({index_: OFFSET_BODY});\n    }\n}\n\n// contracts/base/AgentSecured.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for messaging contracts that are secured by the agent manager.\n * `AgentSecured` relies on `AgentManager` to provide the following functionality:\n * - Keep track of agents and their statuses.\n * - Pass agent-signed statements that were verified by the agent manager.\n * - These statements are considered valid indefinitely, unless the agent is disputed.\n * - Disputes are opened and resolved by the agent manager.\n * \u003e `AgentSecured` implementation should never use statements signed by agents that are disputed.\n */\nabstract contract AgentSecured is MessagingBase, IAgentSecured {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    address public immutable agentManager;\n\n    /// @inheritdoc IAgentSecured\n    address public immutable inbox;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    // (agent index =\u003e their dispute status: flag, openedAt, resolvedAt)\n    mapping(uint32 =\u003e DisputeStatus) internal _disputes;\n\n    /// @dev gap for upgrade safety\n    uint256[49] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    modifier onlyAgentManager() {\n        if (msg.sender != agentManager) revert CallerNotAgentManager();\n        _;\n    }\n\n    modifier onlyInbox() {\n        if (msg.sender != inbox) revert CallerNotInbox();\n        _;\n    }\n\n    constructor(string memory version_, uint32 synapseDomain_, address agentManager_, address inbox_)\n        MessagingBase(version_, synapseDomain_)\n    {\n        agentManager = agentManager_;\n        inbox = inbox_;\n    }\n\n    // ════════════════════════════════════════════ ONLY AGENT MANAGER ═════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external onlyAgentManager {\n        uint40 openedAt = ChainContext.blockTimestamp();\n        DisputeStatus memory status = DisputeStatus({flag: DisputeFlag.Pending, openedAt: openedAt, resolvedAt: 0});\n        _disputes[guardIndex] = status;\n        _disputes[notaryIndex] = status;\n    }\n\n    /// @inheritdoc IAgentSecured\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external onlyAgentManager {\n        // Update the dispute status of the slashed agent first.\n        uint40 resolvedAt = ChainContext.blockTimestamp();\n        _disputes[slashedIndex].flag = DisputeFlag.Slashed;\n        _disputes[slashedIndex].resolvedAt = resolvedAt;\n        // Mark the rival agent as not disputed, if there was an ongoing dispute.\n        if (rivalIndex != 0) {\n            _disputes[rivalIndex].flag = DisputeFlag.None;\n            _disputes[rivalIndex].resolvedAt = resolvedAt;\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function agentStatus(address agent) external view returns (AgentStatus memory) {\n        return _agentStatus(agent);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status) {\n        return _getAgent(index);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory) {\n        return _disputes[agentIndex];\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns status of the given agent: (flag, domain, index).\n    function _agentStatus(address agent) internal view returns (AgentStatus memory) {\n        return IAgentManager(agentManager).agentStatus(agent);\n    }\n\n    /// @dev Returns agent and their status for a given agent index. Returns zero values for non existing indexes.\n    function _getAgent(uint256 index) internal view returns (address agent, AgentStatus memory status) {\n        return IAgentManager(agentManager).getAgent(index);\n    }\n\n    /// @dev Checks if a Dispute exists for the given Notary. This function returns true, if\n    /// Notary is in ongoing Dispute, or if Dispute was resolved not in Notary's favor.\n    /// In both cases we can't trust Notary's data.\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeExists(uint32 notaryIndex) internal view returns (bool) {\n        return _disputes[notaryIndex].flag != DisputeFlag.None;\n    }\n\n    /// @dev Checks if a Notary recently won a Dispute and is still in the \"post-dispute\" timeout period.\n    /// In this period we still can't trust Notary's data, though we can optimistically assume that\n    /// that the data will be correct after the timeout (assuming no new Disputes are opened).\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeTimeout(uint32 notaryIndex) internal view returns (bool) {\n        DisputeStatus memory status = _disputes[notaryIndex];\n        // Exit early if Notary is in ongoing Dispute / slashed.\n        if (status.flag != DisputeFlag.None) return false;\n        // Check if Notary has been in any Dispute at all.\n        if (status.openedAt == 0) return false;\n        // Otherwise check if the Dispute timeout is still active.\n        return block.timestamp \u003c status.resolvedAt + DISPUTE_TIMEOUT_NOTARY;\n    }\n}\n\n// contracts/hubs/StateHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StateHub` is a parent contract for `Origin`. It is responsible for the following:\n/// - Keeping track of the historical Origin Merkle Tree containing all the message hashes.\n/// - Keeping track of the historical Origin States, as well as verifying their validity.\nabstract contract StateHub is AgentSecured, StateHubEvents, IStateHub {\n    using SafeCast for uint256;\n    using StateLib for bytes;\n\n    struct OriginState {\n        uint40 blockNumber;\n        uint40 timestamp;\n        GasData gasData;\n    }\n    // Bits left for tight packing: 80\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Historical Merkle Tree\n    /// Note: Takes two storage slots\n    HistoricalTree private _tree;\n\n    /// @dev All historical contract States\n    OriginState[] private _originStates;\n\n    /// @dev gap for upgrade safety\n    uint256[47] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IStateHub\n    function isValidState(bytes memory statePayload) external view returns (bool isValid) {\n        // This will revert if payload is not a formatted state\n        State state = statePayload.castToState();\n        return _isValidState(state);\n    }\n\n    /// @inheritdoc IStateHub\n    function statesAmount() external view returns (uint256) {\n        return _originStates.length;\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestLatestState() external view returns (bytes memory stateData) {\n        // This never underflows, assuming the contract was initialized\n        return suggestState(_nextNonce() - 1);\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestState(uint32 nonce) public view returns (bytes memory stateData) {\n        // This will revert if nonce is out of range\n        bytes32 root = _tree.root(nonce);\n        return _formatOriginState(_originStates[nonce], root, localDomain, nonce);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Initializes the saved states list by inserting a state for an empty Merkle Tree.\n    function _initializeStates() internal {\n        // This should only be called once, when the contract is initialized\n        // This will revert if _tree.roots is non-empty\n        bytes32 savedRoot = _tree.initializeRoots();\n        // Save root for empty merkle _tree with block number and timestamp of initialization\n        _saveState(savedRoot, _toOriginState());\n    }\n\n    /// @dev Inserts leaf into the Merkle Tree and saves the updated origin State.\n    function _insertAndSave(bytes32 leaf) internal {\n        bytes32 newRoot = _tree.insert(leaf);\n        _saveState(newRoot, _toOriginState());\n    }\n\n    /// @dev Saves an updated state of the Origin contract\n    function _saveState(bytes32 root, OriginState memory state) internal {\n        uint32 nonce = _nextNonce();\n        _originStates.push(state);\n        // Emit event with raw state data\n        emit StateSaved(_formatOriginState(state, root, localDomain, nonce));\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns nonce of the next sent message: the amount of saved States so far.\n    /// This always equals to \"total amount of sent messages\" plus 1.\n    function _nextNonce() internal view returns (uint32) {\n        // TODO: consider using more than 32 bits for origin nonces\n        return _originStates.length.toUint32();\n    }\n\n    /// @dev Checks if a state is valid, i.e. if it matches the historical one.\n    /// Reverts, if state refers to another Origin contract.\n    function _isValidState(State state) internal view returns (bool) {\n        // Check if state refers to this contract\n        if (state.origin() != localDomain) revert IncorrectOriginDomain();\n        // Check if nonce exists\n        uint32 nonce = state.nonce();\n        if (nonce \u003e= _originStates.length) return false;\n        // Check if state root matches the historical one\n        if (state.root() != _tree.root(nonce)) return false;\n        // Check if state metadata matches the historical one\n        return _areEqual(state, _originStates[nonce]);\n    }\n\n    // ═════════════════════════════════════════════ STRUCT FORMATTING ═════════════════════════════════════════════════\n\n    /// @dev Returns a formatted payload for a stored OriginState.\n    function _formatOriginState(OriginState memory originState, bytes32 root, uint32 origin, uint32 nonce)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return StateLib.formatState({\n            root_: root,\n            origin_: origin,\n            nonce_: nonce,\n            blockNumber_: originState.blockNumber,\n            timestamp_: originState.timestamp,\n            gasData_: originState.gasData\n        });\n    }\n\n    /// @dev Child contract should implement the logic for getting the current gas data from the gas oracle\n    /// to be saved as part of the Origin State.\n    // solhint-disable-next-line ordering\n    function _fetchGasData() internal view virtual returns (GasData);\n\n    /// @dev Returns a OriginState struct to save in the contract.\n    function _toOriginState() internal view returns (OriginState memory originState) {\n        originState.blockNumber = ChainContext.blockNumber();\n        originState.timestamp = ChainContext.blockTimestamp();\n        originState.gasData = _fetchGasData();\n    }\n\n    /// @dev Checks that a state and its Origin representation are equal.\n    function _areEqual(State state, OriginState memory originState) internal pure returns (bool) {\n        return state.blockNumber() == originState.blockNumber \u0026\u0026 state.timestamp() == originState.timestamp;\n    }\n}\n\n// contracts/Origin.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Origin` contract is used for sending messages to remote chains. It is done\n/// by inserting the message hashes into the Origin Merkle, which makes it possible to\n/// prove that message was sent using the Merkle proof against the Origin Merkle Root. This essentially\n/// compresses the list of messages into a single 32-byte value that needs to be stored on the destination chain.\n/// `Origin` is responsible for the following:\n/// - Formatting the sent message payloads, and inserting their hashes into the Origin Merkle Tree.\n/// - Keeping track of its own historical states (see parent contract `StateHub`).\n/// - Enforcing minimum tip values for sent base messages based on the provided execution requests.\n/// - Distributing the collected tips upon request from a local `AgentManager` contract.\ncontract Origin is StateHub, OriginEvents, InterfaceOrigin {\n    using MemViewLib for bytes;\n    using MessageLib for bytes;\n    using TipsLib for bytes;\n    using TypeCasts for address;\n\n    address public immutable gasOracle;\n\n    modifier onlyRemoteDestination(uint32 destination) {\n        if (destination == localDomain) revert IncorrectDestinationDomain();\n        _;\n    }\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_, address gasOracle_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {\n        gasOracle = gasOracle_;\n    }\n\n    /// @notice Initializes Origin contract:\n    /// - msg.sender is set as contract owner\n    /// - State of \"empty merkle tree\" is saved\n    function initialize() external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize \"states\": state of an \"empty merkle tree\" is saved\n        _initializeStates();\n    }\n\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable onlyRemoteDestination(destination) returns (uint32 messageNonce, bytes32 messageHash) {\n        // Check that content is not too large\n        if (content.length \u003e MAX_CONTENT_BYTES) revert ContentLengthTooBig();\n        // This will revert if msg.value is lower than value of minimum tips\n        Tips tips = _getMinimumTips(destination, paddedRequest, content.length).matchValue(msg.value);\n        Request request = RequestLib.wrapPadded(paddedRequest);\n        // Format the BaseMessage body\n        bytes memory body = BaseMessageLib.formatBaseMessage({\n            sender_: msg.sender.addressToBytes32(),\n            recipient_: recipient,\n            tips_: tips,\n            request_: request,\n            content_: content\n        });\n        // Send the message\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Base, body);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        onlyAgentManager\n        onlyRemoteDestination(destination)\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // AgentManager (checked via modifier) is responsible for constructing the calldata payload correctly.\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Manager, payload);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function withdrawTips(address recipient, uint256 amount) external onlyAgentManager {\n        if (address(this).balance \u003c amount) revert InsufficientEthBalance();\n        (bool success,) = recipient.call{value: amount}(\"\");\n        if (!success) revert EthTransferFailed();\n        emit TipWithdrawalCompleted(recipient, amount);\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue)\n    {\n        return _getMinimumTips(destination, paddedRequest, contentLength).value();\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Sends the given message to the specified destination. Message hash is inserted\n    /// into the Origin Merkle Tree, which will enable message execution on destination chain.\n    function _sendMessage(uint32 destination, uint32 optimisticPeriod, MessageFlag flag, bytes memory body)\n        internal\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // Format the message header\n        messageNonce = _nextNonce();\n        Header header = flag.encodeHeader({\n            origin_: localDomain,\n            nonce_: messageNonce,\n            destination_: destination,\n            optimisticPeriod_: optimisticPeriod\n        });\n        // Format the full message payload\n        bytes memory msgPayload = MessageLib.formatMessage(header, body);\n        // Insert new leaf into the Origin Merkle Tree and save the updated state\n        messageHash = msgPayload.castToMessage().leaf();\n        _insertAndSave(messageHash);\n        // Emit event with message information\n        emit Sent(messageHash, messageNonce, destination, msgPayload);\n        // Update the gas oracle data. We do this after the provided tips are checked so that\n        // the provided message is sent in the event that the gas oracle data is updated to a higher value.\n        InterfaceGasOracle(gasOracle).updateGasData(destination);\n        // TODO: consider doing this before the message is sent, while adjusting GasOracle.getMinimumTips() to\n        // use the pending gas oracle data.\n    }\n\n    /// @dev Returns the minimum tips for sending a message to the given destination with the given request and content.\n    function _getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        internal\n        view\n        returns (Tips)\n    {\n        return\n            TipsLib.wrapPadded(InterfaceGasOracle(gasOracle).getMinimumTips(destination, paddedRequest, contentLength));\n    }\n\n    /// @dev Gets the current gas data from the gas oracle to be saved as part of the Origin State.\n    function _fetchGasData() internal view override returns (GasData) {\n        return GasDataLib.wrapGasData(InterfaceGasOracle(gasOracle).getGasData());\n    }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"123464:5145:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;123464:5145:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"123464:5145:0:-:0;;;;;;;;","abiDefinition":[],"userDoc":{"kind":"user","methods":{},"notice":"Library for formatting _the header part_ of _the messages used by Origin and Destination_. - Header represents general information for routing a Message for Origin and Destination. - Header occupies a single storage word, and thus is stored on stack instead of being stored in memory. # Header stack layout (from highest bits to lowest) | Position   | Field            | Type   | Bytes | Description                             | | ---------- | ---------------- | ------ | ----- | --------------------------------------- | | (017..016] | flag             | uint8  | 1     | Flag specifying the type of message     | | (016..012] | origin           | uint32 | 4     | Domain where message originated         | | (012..008] | nonce            | uint32 | 4     | Message nonce on the origin domain      | | (008..004] | destination      | uint32 | 4     | Domain where message will be executed   | | (004..000] | optimisticPeriod | uint32 | 4     | Optimistic period that will be enforced |","version":1},"developerDoc":{"kind":"dev","methods":{},"stateVariables":{"SHIFT_DESTINATION":{"details":"Amount of bits to shift to destination field"},"SHIFT_FLAG":{"details":"Amount of bits to shift to flag field"},"SHIFT_NONCE":{"details":"Amount of bits to shift to nonce field"},"SHIFT_ORIGIN":{"details":"Amount of bits to shift to origin field"}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"stateVariables\":{\"SHIFT_DESTINATION\":{\"details\":\"Amount of bits to shift to destination field\"},\"SHIFT_FLAG\":{\"details\":\"Amount of bits to shift to flag field\"},\"SHIFT_NONCE\":{\"details\":\"Amount of bits to shift to nonce field\"},\"SHIFT_ORIGIN\":{\"details\":\"Amount of bits to shift to origin field\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"Library for formatting _the header part_ of _the messages used by Origin and Destination_. - Header represents general information for routing a Message for Origin and Destination. - Header occupies a single storage word, and thus is stored on stack instead of being stored in memory. # Header stack layout (from highest bits to lowest) | Position   | Field            | Type   | Bytes | Description                             | | ---------- | ---------------- | ------ | ----- | --------------------------------------- | | (017..016] | flag             | uint8  | 1     | Flag specifying the type of message     | | (016..012] | origin           | uint32 | 4     | Domain where message originated         | | (012..008] | nonce            | uint32 | 4     | Message nonce on the origin domain      | | (008..004] | destination      | uint32 | 4     | Domain where message will be executed   | | (004..000] | optimisticPeriod | uint32 | 4     | Optimistic period that will be enforced |\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Origin.sol\":\"HeaderLib\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Origin.sol\":{\"keccak256\":\"0x96775924f147f3d1f8df8cdf56731fe52a15af8d8e12e608efb8158c112b18cd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e642a27f5fab3c62b4c02e9754e9e42b1cf2e5381dbea9d3d106d23b7772ebe6\",\"dweb:/ipfs/QmUwn7ZyBvPkjnMuK8ZMSexBUdNQnVtxwyoAyT4DXLQjra\"]}},\"version\":1}"},"hashes":{}},"solidity/Origin.sol:IAgentManager":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/OriginEvents.sol\n\n/// @notice A collection of events emitted by the Origin contract\nabstract contract OriginEvents {\n    /**\n     * @notice Emitted when a new message is sent.\n     * @param messageHash   Hash of message; the leaf inserted to the Merkle tree for the message\n     * @param nonce         Nonce of sent message (starts from 1)\n     * @param destination   Destination domain\n     * @param message       Raw bytes of message\n     */\n    event Sent(bytes32 indexed messageHash, uint32 indexed nonce, uint32 indexed destination, bytes message);\n\n    /**\n     * @notice Emitted when a tip withdrawal is completed.\n     * @param actor     Actor address\n     * @param tip       Tip value, denominated in local domain's wei\n     */\n    event TipWithdrawalCompleted(address actor, uint256 tip);\n}\n\n// contracts/events/StateHubEvents.sol\n\n/// @notice A collection of events emitted by the StateHub contract\nabstract contract StateHubEvents {\n    /**\n     * @notice Emitted when a new Origin State is saved after a message was sent.\n     * @param state     Raw payload with state data\n     */\n    event StateSaved(bytes state);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n    /**\n     * @notice Check that a given state is valid: matches the historical state of Origin contract.\n     * Note: any Agent including an invalid state in their snapshot will be slashed\n     * upon providing the snapshot and agent signature for it to Origin contract.\n     * @dev Will revert if any of these is true:\n     *  - State payload is not properly formatted.\n     * @param statePayload      Raw payload with state data\n     * @return isValid          Whether the provided state is valid\n     */\n    function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns the amount of saved states so far.\n     * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n     */\n    function statesAmount() external view returns (uint256);\n\n    /**\n     * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @return statePayload     Raw payload with the latest state data\n     */\n    function suggestLatestState() external view returns (bytes memory statePayload);\n\n    /**\n     * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @param nonce             Historical nonce to form a state\n     * @return statePayload     Raw payload with historical state data\n     */\n    function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/InterfaceGasOracle.sol\n\ninterface InterfaceGasOracle {\n    /**\n     * @notice Fetches the latest gas data for the chain from `Destination` contract,\n     * and uses it to update the oracle values for the requested chain.\n     * @param domain    Domain to update the gas data for\n     */\n    function updateGasData(uint32 domain) external;\n\n    /**\n     * @notice Returns the gas data for the local chain.\n     */\n    function getGasData() external view returns (uint256 paddedGasData);\n\n    /**\n     * @notice Returns the gas data for the given domain, in the decoded format.\n     * @param domain        Domain of chain to get gas data for\n     * @return gasPrice     Gas price for the chain (in Wei per gas unit)\n     * @return dataPrice    Calldata price (in Wei per byte of content)\n     * @return execBuffer   Tx fee safety buffer for message execution (in Wei)\n     * @return amortAttCost Amortized cost for attestation submission (in Wei)\n     * @return etherPrice   Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n     * @return markup       Markup for the message execution (in BWAD)\n     */\n    function getDecodedGasData(uint32 domain)\n        external\n        view\n        returns (\n            uint256 gasPrice,\n            uint256 dataPrice,\n            uint256 execBuffer,\n            uint256 amortAttCost,\n            uint256 etherPrice,\n            uint256 markup\n        );\n\n    /**\n     * @notice Returns the minimum tips for sending a message to a given destination.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return paddedTips       Padded encoded minimum tips information\n     */\n    function getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 paddedTips);\n}\n\n// contracts/interfaces/InterfaceOrigin.sol\n\ninterface InterfaceOrigin {\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /**\n     * @notice Send a message to the recipient located on destination domain.\n     * @dev Recipient has to conform to IMessageRecipient interface, otherwise message won't be delivered.\n     * Will revert if any of these is true:\n     * - `destination` is equal to contract's local domain\n     * - `content` length is greater than `MAX_CONTENT_BYTES`\n     * - `msg.value` is lower than value of minimum tips for the given message\n     * @param destination           Domain of destination chain\n     * @param recipient             Address of recipient on destination chain as bytes32\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param paddedRequest         Padded encoded message execution request on destination chain\n     * @param content               Raw bytes content of message\n     * @return messageNonce         Nonce of the sent message\n     * @return messageHash          Hash of the sent message\n     */\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable returns (uint32 messageNonce, bytes32 messageHash);\n\n    /**\n     * @notice Send a manager message to the destination domain.\n     * @dev This could only be called by AgentManager, which takes care of encoding the calldata payload.\n     * Note: (msgOrigin, proofMaturity) security args will be added to payload on the destination chain\n     * so that the AgentManager could verify where the Manager Message came from and how mature is the proof.\n     * Note: function is not payable, as no tips are required for sending a manager message.\n     * Will revert if `destination` is equal to contract's local domain.\n     * @param destination           Domain of destination chain\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param payload               Payload for calling AgentManager on destination chain (with extra security args)\n     */\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        returns (uint32 messageNonce, bytes32 messageHash);\n\n    // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Withdraws locked base message tips to the recipient.\n     * @dev Could only be called by a local AgentManager.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function withdrawTips(address recipient, uint256 amount) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the minimum tips value for sending a message to a given destination.\n     * @dev Using at least `tipsValue` as `msg.value` for `sendBaseMessage()`\n     * will guarantee that the message will be accepted.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return tipsValue        Minimum tips value for a message to be accepted\n     */\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue);\n}\n\n// contracts/libs/Constants.sol\n\n// Here we define common constants to enable their easier reusing later.\n\n// ══════════════════════════════════ MERKLE ═══════════════════════════════════\n/// @dev Height of the Agent Merkle Tree\nuint256 constant AGENT_TREE_HEIGHT = 32;\n/// @dev Height of the Origin Merkle Tree\nuint256 constant ORIGIN_TREE_HEIGHT = 32;\n/// @dev Height of the Snapshot Merkle Tree. Allows up to 64 leafs, e.g. up to 32 states\nuint256 constant SNAPSHOT_TREE_HEIGHT = 6;\n// ══════════════════════════════════ STRUCTS ══════════════════════════════════\n/// @dev See Attestation.sol: (bytes32,bytes32,uint32,uint40,uint40): 32+32+4+5+5\nuint256 constant ATTESTATION_LENGTH = 78;\n/// @dev See GasData.sol: (uint16,uint16,uint16,uint16,uint16,uint16): 2+2+2+2+2+2\nuint256 constant GAS_DATA_LENGTH = 12;\n/// @dev See Receipt.sol: (uint32,uint32,bytes32,bytes32,uint8,address,address,address): 4+4+32+32+1+20+20+20\nuint256 constant RECEIPT_LENGTH = 133;\n/// @dev See State.sol: (bytes32,uint32,uint32,uint40,uint40,GasData): 32+4+4+5+5+len(GasData)\nuint256 constant STATE_LENGTH = 50 + GAS_DATA_LENGTH;\n/// @dev Maximum amount of states in a single snapshot. Each state produces two leafs in the tree\nuint256 constant SNAPSHOT_MAX_STATES = 1 \u003c\u003c (SNAPSHOT_TREE_HEIGHT - 1);\n// ══════════════════════════════════ MESSAGE ══════════════════════════════════\n/// @dev See Header.sol: (uint8,uint32,uint32,uint32,uint32): 1+4+4+4+4\nuint256 constant HEADER_LENGTH = 17;\n/// @dev See Request.sol: (uint96,uint64,uint32): 12+8+4\nuint256 constant REQUEST_LENGTH = 24;\n/// @dev See Tips.sol: (uint64,uint64,uint64,uint64): 8+8+8+8\nuint256 constant TIPS_LENGTH = 32;\n/// @dev The amount of discarded last bits when encoding tip values\nuint256 constant TIPS_GRANULARITY = 32;\n/// @dev Tip values could be only the multiples of TIPS_MULTIPLIER\nuint256 constant TIPS_MULTIPLIER = 1 \u003c\u003c TIPS_GRANULARITY;\n// ══════════════════════════════ STATEMENT SALTS ══════════════════════════════\n/// @dev Salts for signing various statements\nbytes32 constant ATTESTATION_VALID_SALT = keccak256(\"ATTESTATION_VALID_SALT\");\nbytes32 constant ATTESTATION_INVALID_SALT = keccak256(\"ATTESTATION_INVALID_SALT\");\nbytes32 constant RECEIPT_VALID_SALT = keccak256(\"RECEIPT_VALID_SALT\");\nbytes32 constant RECEIPT_INVALID_SALT = keccak256(\"RECEIPT_INVALID_SALT\");\nbytes32 constant SNAPSHOT_VALID_SALT = keccak256(\"SNAPSHOT_VALID_SALT\");\nbytes32 constant STATE_INVALID_SALT = keccak256(\"STATE_INVALID_SALT\");\n// ═════════════════════════════════ PROTOCOL ══════════════════════════════════\n/// @dev Optimistic period for new agent roots in LightManager\nuint32 constant AGENT_ROOT_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Timeout between the agent root could be proposed and resolved in LightManager\nuint32 constant AGENT_ROOT_PROPOSAL_TIMEOUT = 12 hours;\nuint32 constant BONDING_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Amount of time that the Notary will not be considered active after they won a dispute\nuint32 constant DISPUTE_TIMEOUT_NOTARY = 12 hours;\n/// @dev Amount of time without fresh data from Notaries before contract owner can resolve stuck disputes manually\nuint256 constant FRESH_DATA_TIMEOUT = 4 hours;\n/// @dev Maximum bytes per message = 2 KiB (somewhat arbitrarily set to begin)\nuint256 constant MAX_CONTENT_BYTES = 2 * 2 ** 10;\n/// @dev Maximum value for the summit tip that could be set in GasOracle\nuint256 constant MAX_SUMMIT_TIP = 0.01 ether;\n\n// contracts/libs/Errors.sol\n\n// ══════════════════════════════ INVALID CALLER ═══════════════════════════════\n\nerror CallerNotAgentManager();\nerror CallerNotDestination();\nerror CallerNotInbox();\nerror CallerNotSummit();\n\n// ══════════════════════════════ INCORRECT DATA ═══════════════════════════════\n\nerror IncorrectAttestation();\nerror IncorrectAgentDomain();\nerror IncorrectAgentIndex();\nerror IncorrectAgentProof();\nerror IncorrectAgentRoot();\nerror IncorrectDataHash();\nerror IncorrectDestinationDomain();\nerror IncorrectOriginDomain();\nerror IncorrectSnapshotProof();\nerror IncorrectSnapshotRoot();\nerror IncorrectState();\nerror IncorrectStatesAmount();\nerror IncorrectTipsProof();\nerror IncorrectVersionLength();\n\nerror IncorrectNonce();\nerror IncorrectSender();\nerror IncorrectRecipient();\n\nerror FlagOutOfRange();\nerror IndexOutOfRange();\nerror NonceOutOfRange();\n\nerror OutdatedNonce();\n\nerror UnformattedAttestation();\nerror UnformattedAttestationReport();\nerror UnformattedBaseMessage();\nerror UnformattedCallData();\nerror UnformattedCallDataPrefix();\nerror UnformattedMessage();\nerror UnformattedReceipt();\nerror UnformattedReceiptReport();\nerror UnformattedSignature();\nerror UnformattedSnapshot();\nerror UnformattedState();\nerror UnformattedStateReport();\n\n// ═══════════════════════════════ MERKLE TREES ════════════════════════════════\n\nerror LeafNotProven();\nerror MerkleTreeFull();\nerror NotEnoughLeafs();\nerror TreeHeightTooLow();\n\n// ═════════════════════════════ OPTIMISTIC PERIOD ═════════════════════════════\n\nerror BaseClientOptimisticPeriod();\nerror MessageOptimisticPeriod();\nerror SlashAgentOptimisticPeriod();\nerror WithdrawTipsOptimisticPeriod();\nerror ZeroProofMaturity();\n\n// ═══════════════════════════════ AGENT MANAGER ═══════════════════════════════\n\nerror AgentNotGuard();\nerror AgentNotNotary();\n\nerror AgentCantBeAdded();\nerror AgentNotActive();\nerror AgentNotActiveNorUnstaking();\nerror AgentNotFraudulent();\nerror AgentNotUnstaking();\nerror AgentUnknown();\n\nerror AgentRootNotProposed();\nerror AgentRootTimeoutNotOver();\n\nerror NotStuck();\n\nerror DisputeAlreadyResolved();\nerror DisputeNotOpened();\nerror DisputeTimeoutNotOver();\nerror GuardInDispute();\nerror NotaryInDispute();\n\nerror MustBeSynapseDomain();\nerror SynapseDomainForbidden();\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\nerror AlreadyExecuted();\nerror AlreadyFailed();\nerror DuplicatedSnapshotRoot();\nerror IncorrectMagicValue();\nerror GasLimitTooLow();\nerror GasSuppliedTooLow();\n\n// ══════════════════════════════════ ORIGIN ═══════════════════════════════════\n\nerror ContentLengthTooBig();\nerror EthTransferFailed();\nerror InsufficientEthBalance();\n\n// ════════════════════════════════ GAS ORACLE ═════════════════════════════════\n\nerror LocalGasDataNotSet();\nerror RemoteGasDataNotSet();\n\n// ═══════════════════════════════════ TIPS ════════════════════════════════════\n\nerror SummitTipTooHigh();\nerror TipsClaimMoreThanEarned();\nerror TipsClaimZero();\nerror TipsOverflow();\nerror TipsValueTooLow();\n\n// ════════════════════════════════ MEMORY VIEW ════════════════════════════════\n\nerror IndexedTooMuch();\nerror ViewOverrun();\nerror OccupiedMemory();\nerror UnallocatedMemory();\nerror PrecompileOutOfGas();\n\n// ═════════════════════════════════ MULTICALL ═════════════════════════════════\n\nerror MulticallFailed();\n\n// contracts/libs/TypeCasts.sol\n\nlibrary TypeCasts {\n    // alignment preserving cast\n    function addressToBytes32(address addr) internal pure returns (bytes32) {\n        return bytes32(uint256(uint160(addr)));\n    }\n\n    // alignment preserving cast\n    function bytes32ToAddress(bytes32 buf) internal pure returns (address) {\n        return address(uint160(uint256(buf)));\n    }\n}\n\n// contracts/libs/stack/Number.sol\n\n/// Number is a compact representation of uint256, that is fit into 16 bits\n/// with the maximum relative error under 0.4%.\ntype Number is uint16;\n\nusing NumberLib for Number global;\n\n/// # Number\n/// Library for compact representation of uint256 numbers.\n/// - Number is stored using mantissa and exponent, each occupying 8 bits.\n/// - Numbers under 2**8 are stored as `mantissa` with `exponent = 0xFF`.\n/// - Numbers at least 2**8 are approximated as `(256 + mantissa) \u003c\u003c exponent`\n/// \u003e - `0 \u003c= mantissa \u003c 256`\n/// \u003e - `0 \u003c= exponent \u003c= 247` (`256 * 2**248` doesn't fit into uint256)\n/// # Number stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type  | Bytes |\n/// | ---------- | -------- | ----- | ----- |\n/// | (002..001] | mantissa | uint8 | 1     |\n/// | (001..000] | exponent | uint8 | 1     |\n\nlibrary NumberLib {\n    /// @dev Amount of bits to shift to mantissa field\n    uint16 private constant SHIFT_MANTISSA = 8;\n\n    /// @notice For bwad math (binary wad) we use 2**64 as \"wad\" unit.\n    /// @dev We are using not using 10**18 as wad, because it is not stored precisely in NumberLib.\n    uint256 internal constant BWAD_SHIFT = 64;\n    uint256 internal constant BWAD = 1 \u003c\u003c BWAD_SHIFT;\n    /// @notice ~0.1% in bwad units.\n    uint256 internal constant PER_MILLE_SHIFT = BWAD_SHIFT - 10;\n    uint256 internal constant PER_MILLE = 1 \u003c\u003c PER_MILLE_SHIFT;\n\n    /// @notice Compresses uint256 number into 16 bits.\n    function compress(uint256 value) internal pure returns (Number) {\n        // Find `msb` such as `2**msb \u003c= value \u003c 2**(msb + 1)`\n        uint256 msb = mostSignificantBit(value);\n        // We want to preserve 9 bits of precision.\n        // The highest bit is always 1, so we can skip it.\n        // The remaining 8 highest bits are stored as mantissa.\n        if (msb \u003c 8) {\n            // Value is less than 2**8, so we can use value as mantissa with \"-1\" exponent.\n            return _encode(uint8(value), 0xFF);\n        } else {\n            // We use `msb - 8` as exponent otherwise. Note that `exponent \u003e= 0`.\n            unchecked {\n                uint256 exponent = msb - 8;\n                // Shifting right by `msb-8` bits will shift the \"remaining 8 highest bits\" into the 8 lowest bits.\n                // uint8() will truncate the highest bit.\n                return _encode(uint8(value \u003e\u003e exponent), uint8(exponent));\n            }\n        }\n    }\n\n    /// @notice Decompresses 16 bits number into uint256.\n    /// @dev The outcome is an approximation of the original number: `(value - value / 256) \u003c number \u003c= value`.\n    function decompress(Number number) internal pure returns (uint256 value) {\n        // Isolate 8 highest bits as the mantissa.\n        uint256 mantissa = Number.unwrap(number) \u003e\u003e SHIFT_MANTISSA;\n        // This will truncate the highest bits, leaving only the exponent.\n        uint256 exponent = uint8(Number.unwrap(number));\n        if (exponent == 0xFF) {\n            return mantissa;\n        } else {\n            unchecked {\n                return (256 + mantissa) \u003c\u003c (exponent);\n            }\n        }\n    }\n\n    /// @dev Returns the most significant bit of `x`\n    /// https://solidity-by-example.org/bitwise/\n    function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\n        // To find `msb` we determine it bit by bit, starting from the highest one.\n        // `0 \u003c= msb \u003c= 255`, so we start from the highest bit, 1\u003c\u003c7 == 128.\n        // If `x` is at least 2**128, then the highest bit of `x` is at least 128.\n        // solhint-disable no-inline-assembly\n        assembly {\n            // `f` is set to 1\u003c\u003c7 if `x \u003e= 2**128` and to 0 otherwise.\n            let f := shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\n            // If `x \u003e= 2**128` then set `msb` highest bit to 1 and shift `x` right by 128.\n            // Otherwise, `msb` remains 0 and `x` remains unchanged.\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        // `x` is now at most 2**128 - 1. Continue the same way, the next highest bit is 1\u003c\u003c6 == 64.\n        assembly {\n            // `f` is set to 1\u003c\u003c6 if `x \u003e= 2**64` and to 0 otherwise.\n            let f := shl(6, gt(x, 0xFFFFFFFFFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c5 if `x \u003e= 2**32` and to 0 otherwise.\n            let f := shl(5, gt(x, 0xFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c4 if `x \u003e= 2**16` and to 0 otherwise.\n            let f := shl(4, gt(x, 0xFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c3 if `x \u003e= 2**8` and to 0 otherwise.\n            let f := shl(3, gt(x, 0xFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c2 if `x \u003e= 2**4` and to 0 otherwise.\n            let f := shl(2, gt(x, 0xF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c1 if `x \u003e= 2**2` and to 0 otherwise.\n            let f := shl(1, gt(x, 0x3))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1 if `x \u003e= 2**1` and to 0 otherwise.\n            let f := gt(x, 0x1)\n            msb := or(msb, f)\n        }\n    }\n\n    /// @dev Wraps (mantissa, exponent) pair into Number.\n    function _encode(uint8 mantissa, uint8 exponent) private pure returns (Number) {\n        // Casts below are upcasts, so they are safe.\n        return Number.wrap(uint16(mantissa) \u003c\u003c SHIFT_MANTISSA | uint16(exponent));\n    }\n}\n\n// contracts/libs/stack/Request.sol\n\n/// Request is encoded data with \"message execution request\".\ntype Request is uint192;\n\nusing RequestLib for Request global;\n\n/// Library for formatting _the request part_ of _the base messages_.\n/// - Request represents a message sender requirements for the message execution on the destination chain.\n/// - Request occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n/// \u003e gasDrop field is included for future compatibility and is ignored at the moment.\n///\n/// # Request stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type   | Bytes | Description                                          |\n/// | ---------- | -------- | ------ | ----- | ---------------------------------------------------- |\n/// | (024..012] | gasDrop  | uint96 | 12    | Minimum amount of gas token to drop to the recipient |\n/// | (012..004] | gasLimit | uint64 | 8     | Minimum amount of gas units to supply for execution  |\n/// | (004..000] | version  | uint32 | 4     | Base message version to pass to the recipient        |\n\nlibrary RequestLib {\n    /// @dev Amount of bits to shift to gasDrop field\n    uint192 private constant SHIFT_GAS_DROP = 12 * 8;\n    /// @dev Amount of bits to shift to gasLimit field\n    uint192 private constant SHIFT_GAS_LIMIT = 4 * 8;\n\n    /// @notice Returns an encoded request with the given fields\n    /// @param gasDrop_     Minimum amount of gas token to drop to the recipient (ignored at the moment)\n    /// @param gasLimit_    Minimum amount of gas units to supply for execution\n    /// @param version_     Base message version to pass to the recipient\n    function encodeRequest(uint96 gasDrop_, uint64 gasLimit_, uint32 version_) internal pure returns (Request) {\n        // Casts below are upcasts, so they are safe\n        return Request.wrap(uint192(gasDrop_) \u003c\u003c SHIFT_GAS_DROP | uint192(gasLimit_) \u003c\u003c SHIFT_GAS_LIMIT | version_);\n    }\n\n    /// @notice Wraps the padded encoded request into a Request-typed value.\n    /// @dev The \"padded\" request is simply an encoded request casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded requests\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedRequest) internal pure returns (Request) {\n        // Casting to uint192 will truncate the highest bits, which is the behavior we want\n        return Request.wrap(uint192(paddedRequest));\n    }\n\n    /// @notice Returns the requested of gas token to drop to the recipient.\n    function gasDrop(Request request) internal pure returns (uint96) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return uint96(Request.unwrap(request) \u003e\u003e SHIFT_GAS_DROP);\n    }\n\n    /// @notice Returns the requested minimum amount of gas units to supply for execution.\n    function gasLimit(Request request) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Request.unwrap(request) \u003e\u003e SHIFT_GAS_LIMIT);\n    }\n\n    /// @notice Returns the requested base message version to pass to the recipient.\n    function version(Request request) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Request.unwrap(request));\n    }\n}\n\n// node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        require(value \u003c= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        require(value \u003c= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        require(value \u003c= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value \u003c= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        require(value \u003c= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        require(value \u003c= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        require(value \u003c= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        require(value \u003c= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        require(value \u003c= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        require(value \u003c= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        require(value \u003c= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        require(value \u003c= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        require(value \u003c= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        require(value \u003c= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        require(value \u003c= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value \u003c= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        require(value \u003c= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        require(value \u003c= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        require(value \u003c= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value \u003c= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        require(value \u003c= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        require(value \u003c= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        require(value \u003c= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value \u003c= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        require(value \u003c= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        require(value \u003c= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        require(value \u003c= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value \u003c= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        require(value \u003c= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value \u003c= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value \u003c= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     *\n     * _Available since v3.0._\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value \u003e= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     *\n     * _Available since v3.0._\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value \u003c= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     *\n     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length \u003e 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance \u003e= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance \u003e= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length \u003e 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n\n// contracts/base/MultiCallable.sol\n\n/// @notice Collection of Multicall utilities. Fork of Multicall3:\n/// https://github.com/mds1/multicall/blob/master/src/Multicall3.sol\nabstract contract MultiCallable {\n    struct Call {\n        bool allowFailure;\n        bytes callData;\n    }\n\n    struct Result {\n        bool success;\n        bytes returnData;\n    }\n\n    /// @notice Aggregates a few calls to this contract into one multicall without modifying `msg.sender`.\n    function multicall(Call[] calldata calls) external returns (Result[] memory callResults) {\n        uint256 amount = calls.length;\n        callResults = new Result[](amount);\n        Call calldata call_;\n        for (uint256 i = 0; i \u003c amount;) {\n            call_ = calls[i];\n            Result memory result = callResults[i];\n            // We perform a delegate call to ourselves here. Delegate call does not modify `msg.sender`, so\n            // this will have the same effect as if `msg.sender` performed all the calls themselves one by one.\n            // solhint-disable-next-line avoid-low-level-calls\n            (result.success, result.returnData) = address(this).delegatecall(call_.callData);\n            // solhint-disable-next-line no-inline-assembly\n            assembly {\n                // Revert if the call fails and failure is not allowed\n                // `allowFailure := calldataload(call_)` and `success := mload(result)`\n                if iszero(or(calldataload(call_), mload(result))) {\n                    // Revert with `0x4d6a2328` (function selector for `MulticallFailed()`)\n                    mstore(0x00, 0x4d6a232800000000000000000000000000000000000000000000000000000000)\n                    revert(0x00, 0x04)\n                }\n            }\n            unchecked {\n                ++i;\n            }\n        }\n    }\n}\n\n// contracts/base/Version.sol\n\n/**\n * @title Versioned\n * @notice Version getter for contracts. Doesn't use any storage slots, meaning\n * it will never cause any troubles with the upgradeable contracts. For instance, this contract\n * can be added or removed from the inheritance chain without shifting the storage layout.\n */\nabstract contract Versioned {\n    /**\n     * @notice Struct that is mimicking the storage layout of a string with 32 bytes or less.\n     * Length is limited by 32, so the whole string payload takes two memory words:\n     * @param length    String length\n     * @param data      String characters\n     */\n    struct _ShortString {\n        uint256 length;\n        bytes32 data;\n    }\n\n    /// @dev Length of the \"version string\"\n    uint256 private immutable _length;\n    /// @dev Bytes representation of the \"version string\".\n    /// Strings with length over 32 are not supported!\n    bytes32 private immutable _data;\n\n    constructor(string memory version_) {\n        _length = bytes(version_).length;\n        if (_length \u003e 32) revert IncorrectVersionLength();\n        // bytes32 is left-aligned =\u003e this will store the byte representation of the string\n        // with the trailing zeroes to complete the 32-byte word\n        _data = bytes32(bytes(version_));\n    }\n\n    function version() external view returns (string memory versionString) {\n        // Load the immutable values to form the version string\n        _ShortString memory str = _ShortString(_length, _data);\n        // The only way to do this cast is doing some dirty assembly\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            versionString := str\n        }\n    }\n}\n\n// contracts/libs/ChainContext.sol\n\n/// @notice Library for accessing chain context variables as tightly packed integers.\n/// Messaging contracts should rely on this library for accessing chain context variables\n/// instead of doing the casting themselves.\nlibrary ChainContext {\n    using SafeCast for uint256;\n\n    /// @notice Returns the current block number as uint40.\n    /// @dev Reverts if block number is greater than 40 bits, which is not supposed to happen\n    /// until the block.timestamp overflows (assuming block time is at least 1 second).\n    function blockNumber() internal view returns (uint40) {\n        return block.number.toUint40();\n    }\n\n    /// @notice Returns the current block timestamp as uint40.\n    /// @dev Reverts if block timestamp is greater than 40 bits, which is\n    /// supposed to happen approximately in year 36835.\n    function blockTimestamp() internal view returns (uint40) {\n        return block.timestamp.toUint40();\n    }\n\n    /// @notice Returns the chain id as uint32.\n    /// @dev Reverts if chain id is greater than 32 bits, which is not\n    /// supposed to happen in production.\n    function chainId() internal view returns (uint32) {\n        return block.chainid.toUint32();\n    }\n}\n\n// contracts/libs/Structures.sol\n\n// Here we define common enums and structures to enable their easier reusing later.\n\n// ═══════════════════════════════ AGENT STATUS ════════════════════════════════\n\n/// @dev Potential statuses for the off-chain bonded agent:\n/// - Unknown: never provided a bond =\u003e signature not valid\n/// - Active: has a bond in BondingManager =\u003e signature valid\n/// - Unstaking: has a bond in BondingManager, initiated the unstaking =\u003e signature not valid\n/// - Resting: used to have a bond in BondingManager, successfully unstaked =\u003e signature not valid\n/// - Fraudulent: proven to commit fraud, value in Merkle Tree not updated =\u003e signature not valid\n/// - Slashed: proven to commit fraud, value in Merkle Tree was updated =\u003e signature not valid\n/// Unstaked agent could later be added back to THE SAME domain by staking a bond again.\n/// Honest agent: Unknown -\u003e Active -\u003e unstaking -\u003e Resting -\u003e Active ...\n/// Malicious agent: Unknown -\u003e Active -\u003e Fraudulent -\u003e Slashed\n/// Malicious agent: Unknown -\u003e Active -\u003e Unstaking -\u003e Fraudulent -\u003e Slashed\nenum AgentFlag {\n    Unknown,\n    Active,\n    Unstaking,\n    Resting,\n    Fraudulent,\n    Slashed\n}\n\n/// @notice Struct for storing an agent in the BondingManager contract.\nstruct AgentStatus {\n    AgentFlag flag;\n    uint32 domain;\n    uint32 index;\n}\n// 184 bits available for tight packing\n\nusing StructureUtils for AgentStatus global;\n\n/// @notice Potential statuses of an agent in terms of being in dispute\n/// - None: agent is not in dispute\n/// - Pending: agent is in unresolved dispute\n/// - Slashed: agent was in dispute that lead to agent being slashed\n/// Note: agent who won the dispute has their status reset to None\nenum DisputeFlag {\n    None,\n    Pending,\n    Slashed\n}\n\n/// @notice Struct for storing dispute status of an agent.\n/// @param flag         Dispute flag: None/Pending/Slashed.\n/// @param openedAt     Timestamp when the latest agent dispute was opened (zero if not opened).\n/// @param resolvedAt   Timestamp when the latest agent dispute was resolved (zero if not resolved).\nstruct DisputeStatus {\n    DisputeFlag flag;\n    uint40 openedAt;\n    uint40 resolvedAt;\n}\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\n/// @notice Struct representing the status of Destination contract.\n/// @param snapRootTime     Timestamp when latest snapshot root was accepted\n/// @param agentRootTime    Timestamp when latest agent root was accepted\n/// @param notaryIndex      Index of Notary who signed the latest agent root\nstruct DestinationStatus {\n    uint40 snapRootTime;\n    uint40 agentRootTime;\n    uint32 notaryIndex;\n}\n\n// ═══════════════════════════════ EXECUTION HUB ═══════════════════════════════\n\n/// @notice Potential statuses of the message in Execution Hub.\n/// - None: there hasn't been a valid attempt to execute the message yet\n/// - Failed: there was a valid attempt to execute the message, but recipient reverted\n/// - Success: there was a valid attempt to execute the message, and recipient did not revert\n/// Note: message can be executed until its status is Success\nenum MessageStatus {\n    None,\n    Failed,\n    Success\n}\n\nlibrary StructureUtils {\n    /// @notice Checks that Agent is Active\n    function verifyActive(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active) {\n            revert AgentNotActive();\n        }\n    }\n\n    /// @notice Checks that Agent is Unstaking\n    function verifyUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Unstaking) {\n            revert AgentNotUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Active or Unstaking\n    function verifyActiveUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active \u0026\u0026 status.flag != AgentFlag.Unstaking) {\n            revert AgentNotActiveNorUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Fraudulent\n    function verifyFraudulent(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Fraudulent) {\n            revert AgentNotFraudulent();\n        }\n    }\n\n    /// @notice Checks that Agent is not Unknown\n    function verifyKnown(AgentStatus memory status) internal pure {\n        if (status.flag == AgentFlag.Unknown) {\n            revert AgentUnknown();\n        }\n    }\n}\n\n// contracts/libs/memory/MemView.sol\n\n/// @dev MemView is an untyped view over a portion of memory to be used instead of `bytes memory`\ntype MemView is uint256;\n\n/// @dev Attach library functions to MemView\nusing MemViewLib for MemView global;\n\n/// @notice Library for operations with the memory views.\n/// Forked from https://github.com/summa-tx/memview-sol with several breaking changes:\n/// - The codebase is ported to Solidity 0.8\n/// - Custom errors are added\n/// - The runtime type checking is replaced with compile-time check provided by User-Defined Value Types\n///   https://docs.soliditylang.org/en/latest/types.html#user-defined-value-types\n/// - uint256 is used as the underlying type for the \"memory view\" instead of bytes29.\n///   It is wrapped into MemView custom type in order not to be confused with actual integers.\n/// - Therefore the \"type\" field is discarded, allowing to allocate 16 bytes for both view location and length\n/// - The documentation is expanded\n/// - Library functions unused by the rest of the codebase are removed\n//  - Very pretty code separators are added :)\nlibrary MemViewLib {\n    /// @notice Stack layout for uint256 (from highest bits to lowest)\n    /// (32 .. 16]      loc     16 bytes    Memory address of underlying bytes\n    /// (16 .. 00]      len     16 bytes    Length of underlying bytes\n\n    // ═══════════════════════════════════════════ BUILDING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Instantiate a new untyped memory view. This should generally not be called directly.\n     * Prefer `ref` wherever possible.\n     * @param loc_          The memory address\n     * @param len_          The length\n     * @return The new view with the specified location and length\n     */\n    function build(uint256 loc_, uint256 len_) internal pure returns (MemView) {\n        uint256 end_ = loc_ + len_;\n        // Make sure that a view is not constructed that points to unallocated memory\n        // as this could be indicative of a buffer overflow attack\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            if gt(end_, mload(0x40)) { end_ := 0 }\n        }\n        if (end_ == 0) {\n            revert UnallocatedMemory();\n        }\n        return _unsafeBuildUnchecked(loc_, len_);\n    }\n\n    /**\n     * @notice Instantiate a memory view from a byte array.\n     * @dev Note that due to Solidity memory representation, it is not possible to\n     * implement a deref, as the `bytes` type stores its len in memory.\n     * @param arr           The byte array\n     * @return The memory view over the provided byte array\n     */\n    function ref(bytes memory arr) internal pure returns (MemView) {\n        uint256 len_ = arr.length;\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 loc_;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // We add 0x20, so that the view starts exactly where the array data starts\n            loc_ := add(arr, 0x20)\n        }\n        return build(loc_, len_);\n    }\n\n    // ════════════════════════════════════════════ CLONING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to the new memory.\n     * @param memView       The memory view\n     * @return arr          The cloned byte array\n     */\n    function clone(MemView memView) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        unchecked {\n            _unsafeCopyTo(memView, ptr + 0x20);\n        }\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 len_ = memView.len();\n        uint256 footprint_ = memView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    /**\n     * @notice Copies all views, joins them into a new bytearray.\n     * @param memViews      The memory views\n     * @return arr          The new byte array with joined data behind the given views\n     */\n    function join(MemView[] memory memViews) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        MemView newView;\n        unchecked {\n            newView = _unsafeJoin(memViews, ptr + 0x20);\n        }\n        uint256 len_ = newView.len();\n        uint256 footprint_ = newView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    // ══════════════════════════════════════════ INSPECTING MEMORY VIEW ═══════════════════════════════════════════════\n\n    /**\n     * @notice Returns the memory address of the underlying bytes.\n     * @param memView       The memory view\n     * @return loc_         The memory address\n     */\n    function loc(MemView memView) internal pure returns (uint256 loc_) {\n        // loc is stored in the highest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u003e\u003e 128;\n    }\n\n    /**\n     * @notice Returns the number of bytes of the view.\n     * @param memView       The memory view\n     * @return len_         The length of the view\n     */\n    function len(MemView memView) internal pure returns (uint256 len_) {\n        // len is stored in the lowest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u0026 type(uint128).max;\n    }\n\n    /**\n     * @notice Returns the endpoint of `memView`.\n     * @param memView       The memory view\n     * @return end_         The endpoint of `memView`\n     */\n    function end(MemView memView) internal pure returns (uint256 end_) {\n        // The endpoint never overflows uint128, let alone uint256, so we could use unchecked math here\n        unchecked {\n            return memView.loc() + memView.len();\n        }\n    }\n\n    /**\n     * @notice Returns the number of memory words this memory view occupies, rounded up.\n     * @param memView       The memory view\n     * @return words_       The number of memory words\n     */\n    function words(MemView memView) internal pure returns (uint256 words_) {\n        // returning ceil(length / 32.0)\n        unchecked {\n            return (memView.len() + 31) \u003e\u003e 5;\n        }\n    }\n\n    /**\n     * @notice Returns the in-memory footprint of a fresh copy of the view.\n     * @param memView       The memory view\n     * @return footprint_   The in-memory footprint of a fresh copy of the view.\n     */\n    function footprint(MemView memView) internal pure returns (uint256 footprint_) {\n        // words() * 32\n        return memView.words() \u003c\u003c 5;\n    }\n\n    // ════════════════════════════════════════════ HASHING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the keccak256 hash of the underlying memory\n     * @param memView       The memory view\n     * @return digest       The keccak256 hash of the underlying memory\n     */\n    function keccak(MemView memView) internal pure returns (bytes32 digest) {\n        uint256 loc_ = memView.loc();\n        uint256 len_ = memView.len();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            digest := keccak256(loc_, len_)\n        }\n    }\n\n    /**\n     * @notice Adds a salt to the keccak256 hash of the underlying data and returns the keccak256 hash of the\n     * resulting data.\n     * @param memView       The memory view\n     * @return digestSalted keccak256(salt, keccak256(memView))\n     */\n    function keccakSalted(MemView memView, bytes32 salt) internal pure returns (bytes32 digestSalted) {\n        return keccak256(bytes.concat(salt, memView.keccak()));\n    }\n\n    // ════════════════════════════════════════════ SLICING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Safe slicing without memory modification.\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the given index\n     */\n    function slice(MemView memView, uint256 index_, uint256 len_) internal pure returns (MemView) {\n        uint256 loc_ = memView.loc();\n        // Ensure it doesn't overrun the view\n        if (loc_ + index_ + len_ \u003e memView.end()) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // loc_ + index_ \u003c= memView.end()\n            return build({loc_: loc_ + index_, len_: len_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing bytes from `index` to end(memView).\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @return The new view for the slice starting from the given index until the initial view endpoint\n     */\n    function sliceFrom(MemView memView, uint256 index_) internal pure returns (MemView) {\n        uint256 len_ = memView.len();\n        // Ensure it doesn't overrun the view\n        if (index_ \u003e len_) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // index_ \u003c= len_ =\u003e memView.loc() + index_ \u003c= memView.loc() + memView.len() == memView.end()\n            return build({loc_: memView.loc() + index_, len_: len_ - index_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the first `len` bytes.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the initial view beginning\n     */\n    function prefix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        return memView.slice({index_: 0, len_: len_});\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the last `len` byte.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length until the initial view endpoint\n     */\n    function postfix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        uint256 viewLen = memView.len();\n        // Ensure it doesn't overrun the view\n        if (len_ \u003e viewLen) {\n            revert ViewOverrun();\n        }\n        // Could do the unchecked math due to the check above\n        uint256 index_;\n        unchecked {\n            index_ = viewLen - len_;\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // len_ \u003c= memView.len() =\u003e memView.loc() \u003c= loc_ \u003c= memView.end()\n            return build({loc_: memView.loc() + viewLen - len_, len_: len_});\n        }\n    }\n\n    // ═══════════════════════════════════════════ INDEXING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Load up to 32 bytes from the view onto the stack.\n     * @dev Returns a bytes32 with only the `bytes_` HIGHEST bytes set.\n     * This can be immediately cast to a smaller fixed-length byte array.\n     * To automatically cast to an integer, use `indexUint`.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return result       The 32 byte result having only `bytes_` highest bytes set\n     */\n    function index(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (bytes32 result) {\n        if (bytes_ == 0) {\n            return bytes32(0);\n        }\n        // Can't load more than 32 bytes to the stack in one go\n        if (bytes_ \u003e 32) {\n            revert IndexedTooMuch();\n        }\n        // The last indexed byte should be within view boundaries\n        if (index_ + bytes_ \u003e memView.len()) {\n            revert ViewOverrun();\n        }\n        uint256 bitLength = bytes_ \u003c\u003c 3; // bytes_ * 8\n        uint256 loc_ = memView.loc();\n        // Get a mask with `bitLength` highest bits set\n        uint256 mask;\n        // 0x800...00 binary representation is 100...00\n        // sar stands for \"signed arithmetic shift\": https://en.wikipedia.org/wiki/Arithmetic_shift\n        // sar(N-1, 100...00) = 11...100..00, with exactly N highest bits set to 1\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            mask := sar(sub(bitLength, 1), 0x8000000000000000000000000000000000000000000000000000000000000000)\n        }\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load a full word using index offset, and apply mask to ignore non-relevant bytes\n            result := and(mload(add(loc_, index_)), mask)\n        }\n    }\n\n    /**\n     * @notice Parse an unsigned integer from the view at `index`.\n     * @dev Requires that the view have \u003e= `bytes_` bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return The unsigned integer\n     */\n    function indexUint(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (uint256) {\n        bytes32 indexedBytes = memView.index(index_, bytes_);\n        // `index()` returns left-aligned `bytes_`, while integers are right-aligned\n        // Shifting here to right-align with the full 32 bytes word: need to shift right `(32 - bytes_)` bytes\n        unchecked {\n            // memView.index() reverts when bytes_ \u003e 32, thus unchecked math\n            return uint256(indexedBytes) \u003e\u003e ((32 - bytes_) \u003c\u003c 3);\n        }\n    }\n\n    /**\n     * @notice Parse an address from the view at `index`.\n     * @dev Requires that the view have \u003e= 20 bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @return The address\n     */\n    function indexAddress(MemView memView, uint256 index_) internal pure returns (address) {\n        // index 20 bytes as `uint160`, and then cast to `address`\n        return address(uint160(memView.indexUint(index_, 20)));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns a memory view over the specified memory location\n    /// without checking if it points to unallocated memory.\n    function _unsafeBuildUnchecked(uint256 loc_, uint256 len_) private pure returns (MemView) {\n        // There is no scenario where loc or len would overflow uint128, so we omit this check.\n        // We use the highest 128 bits to encode the location and the lowest 128 bits to encode the length.\n        return MemView.wrap((loc_ \u003c\u003c 128) | len_);\n    }\n\n    /**\n     * @notice Copy the view to a location, return an unsafe memory reference\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memView       The memory view\n     * @param newLoc        The new location to copy the underlying view data\n     * @return The memory view over the unsafe memory with the copied underlying data\n     */\n    function _unsafeCopyTo(MemView memView, uint256 newLoc) private view returns (MemView) {\n        uint256 len_ = memView.len();\n        uint256 oldLoc = memView.loc();\n\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (newLoc \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        bool res;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // use the identity precompile (0x04) to copy\n            res := staticcall(gas(), 0x04, oldLoc, len_, newLoc, len_)\n        }\n        if (!res) revert PrecompileOutOfGas();\n        return _unsafeBuildUnchecked({loc_: newLoc, len_: len_});\n    }\n\n    /**\n     * @notice Join the views in memory, return an unsafe reference to the memory.\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memViews      The memory views\n     * @return The conjoined view pointing to the new memory\n     */\n    function _unsafeJoin(MemView[] memory memViews, uint256 location) private view returns (MemView) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (location \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        // Copy the views to the specified location one by one, by tracking the amount of copied bytes so far\n        uint256 offset = 0;\n        for (uint256 i = 0; i \u003c memViews.length;) {\n            MemView memView = memViews[i];\n            // We can use the unchecked math here as location + sum(view.length) will never overflow uint256\n            unchecked {\n                _unsafeCopyTo(memView, location + offset);\n                offset += memView.len();\n                ++i;\n            }\n        }\n        return _unsafeBuildUnchecked({loc_: location, len_: offset});\n    }\n}\n\n// contracts/libs/merkle/MerkleMath.sol\n\nlibrary MerkleMath {\n    // ═════════════════════════════════════════ BASIC MERKLE CALCULATIONS ═════════════════════════════════════════════\n\n    /**\n     * @notice Calculates the merkle root for the given leaf and merkle proof.\n     * @dev Will revert if proof length exceeds the tree height.\n     * @param index     Index of `leaf` in tree\n     * @param leaf      Leaf of the merkle tree\n     * @param proof     Proof of inclusion of `leaf` in the tree\n     * @param height    Height of the merkle tree\n     * @return root_    Calculated Merkle Root\n     */\n    function proofRoot(uint256 index, bytes32 leaf, bytes32[] memory proof, uint256 height)\n        internal\n        pure\n        returns (bytes32 root_)\n    {\n        // Proof length could not exceed the tree height\n        uint256 proofLen = proof.length;\n        if (proofLen \u003e height) revert TreeHeightTooLow();\n        root_ = leaf;\n        /// @dev Apply unchecked to all ++h operations\n        unchecked {\n            // Go up the tree levels from the leaf following the proof\n            for (uint256 h = 0; h \u003c proofLen; ++h) {\n                // Get a sibling node on current level: this is proof[h]\n                root_ = getParent(root_, proof[h], index, h);\n            }\n            // Go up to the root: the remaining siblings are EMPTY\n            for (uint256 h = proofLen; h \u003c height; ++h) {\n                root_ = getParent(root_, bytes32(0), index, h);\n            }\n        }\n    }\n\n    /**\n     * @notice Calculates the parent of a node on the path from one of the leafs to root.\n     * @param node          Node on a path from tree leaf to root\n     * @param sibling       Sibling for a given node\n     * @param leafIndex     Index of the tree leaf\n     * @param nodeHeight    \"Level height\" for `node` (ZERO for leafs, ORIGIN_TREE_HEIGHT for root)\n     */\n    function getParent(bytes32 node, bytes32 sibling, uint256 leafIndex, uint256 nodeHeight)\n        internal\n        pure\n        returns (bytes32 parent)\n    {\n        // Index for `node` on its \"tree level\" is (leafIndex / 2**height)\n        // \"Left child\" has even index, \"right child\" has odd index\n        if ((leafIndex \u003e\u003e nodeHeight) \u0026 1 == 0) {\n            // Left child\n            return getParent(node, sibling);\n        } else {\n            // Right child\n            return getParent(sibling, node);\n        }\n    }\n\n    /// @notice Calculates the parent of tow nodes in the merkle tree.\n    /// @dev We use implementation with H(0,0) = 0\n    /// This makes EVERY empty node in the tree equal to ZERO,\n    /// saving us from storing H(0,0), H(H(0,0), H(0, 0)), and so on\n    /// @param leftChild    Left child of the calculated node\n    /// @param rightChild   Right child of the calculated node\n    /// @return parent      Value for the node having above mentioned children\n    function getParent(bytes32 leftChild, bytes32 rightChild) internal pure returns (bytes32 parent) {\n        if (leftChild == bytes32(0) \u0026\u0026 rightChild == bytes32(0)) {\n            return 0;\n        } else {\n            return keccak256(bytes.concat(leftChild, rightChild));\n        }\n    }\n\n    // ════════════════════════════════ ROOT/PROOF CALCULATION FOR A LIST OF LEAFS ═════════════════════════════════════\n\n    /**\n     * @notice Calculates merkle root for a list of given leafs.\n     * Merkle Tree is constructed by padding the list with ZERO values for leafs until list length is `2**height`.\n     * Merkle Root is calculated for the constructed tree, and then saved in `leafs[0]`.\n     * \u003e Note:\n     * \u003e - `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * \u003e - Caller is expected not to reuse `hashes` list after the call, and only use `leafs[0]` value,\n     * which is guaranteed to contain the calculated merkle root.\n     * \u003e - root is calculated using the `H(0,0) = 0` Merkle Tree implementation. See MerkleTree.sol for details.\n     * @dev Amount of leaves should be at most `2**height`\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param height    Height of the Merkle Tree to construct\n     */\n    function calculateRoot(bytes32[] memory hashes, uint256 height) internal pure {\n        uint256 levelLength = hashes.length;\n        // Amount of hashes could not exceed amount of leafs in tree with the given height\n        if (levelLength \u003e (1 \u003c\u003c height)) revert TreeHeightTooLow();\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\": the amount of iterations for the for loop above.\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n            }\n        }\n    }\n\n    /**\n     * @notice Generates a proof of inclusion of a leaf in the list. If the requested index is outside\n     * of the list range, generates a proof of inclusion for an empty leaf (proof of non-inclusion).\n     * The Merkle Tree is constructed by padding the list with ZERO values until list length is a power of two\n     * __AND__ index is in the extended list range. For example:\n     *  - `hashes.length == 6` and `0 \u003c= index \u003c= 7` will \"extend\" the list to 8 entries.\n     *  - `hashes.length == 6` and `7 \u003c index \u003c= 15` will \"extend\" the list to 16 entries.\n     * \u003e Note: `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * Caller is expected not to reuse `hashes` list after the call.\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param index     Leaf index to generate the proof for\n     * @return proof    Generated merkle proof\n     */\n    function calculateProof(bytes32[] memory hashes, uint256 index) internal pure returns (bytes32[] memory proof) {\n        // Use only meaningful values for the shortened proof\n        // Check if index is within the list range (we want to generates proofs for outside leafs as well)\n        uint256 height = getHeight(index \u003c hashes.length ? hashes.length : (index + 1));\n        proof = new bytes32[](height);\n        uint256 levelLength = hashes.length;\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Use sibling for the merkle proof; `index^1` is index of our sibling\n                proof[h] = (index ^ 1 \u003c levelLength) ? hashes[index ^ 1] : bytes32(0);\n\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\"\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n                // Traverse to parent node\n                index \u003e\u003e= 1;\n            }\n        }\n    }\n\n    /// @notice Returns the height of the tree having a given amount of leafs.\n    function getHeight(uint256 leafs) internal pure returns (uint256 height) {\n        uint256 amount = 1;\n        while (amount \u003c leafs) {\n            unchecked {\n                ++height;\n            }\n            amount \u003c\u003c= 1;\n        }\n    }\n}\n\n// contracts/libs/stack/GasData.sol\n\n/// GasData in encoded data with \"basic information about gas prices\" for some chain.\ntype GasData is uint96;\n\nusing GasDataLib for GasData global;\n\n/// ChainGas is encoded data with given chain's \"basic information about gas prices\".\ntype ChainGas is uint128;\n\nusing GasDataLib for ChainGas global;\n\n/// Library for encoding and decoding GasData and ChainGas structs.\n/// # GasData\n/// `GasData` is a struct to store the \"basic information about gas prices\", that could\n/// be later used to approximate the cost of a message execution, and thus derive the\n/// minimal tip values for sending a message to the chain.\n/// \u003e - `GasData` is supposed to be cached by `GasOracle` contract, allowing to store the\n/// \u003e approximates instead of the exact values, and thus save on storage costs.\n/// \u003e - For instance, if `GasOracle` only updates the values on +- 10% change, having an\n/// \u003e 0.4% error on the approximates would be acceptable.\n/// `GasData` is supposed to be included in the Origin's state, which are synced across\n/// chains using Agent-signed snapshots and attestations.\n/// ## GasData stack layout (from highest bits to lowest)\n///\n/// | Position   | Field        | Type   | Bytes | Description                                         |\n/// | ---------- | ------------ | ------ | ----- | --------------------------------------------------- |\n/// | (012..010] | gasPrice     | uint16 | 2     | Gas price for the chain (in Wei per gas unit)       |\n/// | (010..008] | dataPrice    | uint16 | 2     | Calldata price (in Wei per byte of content)         |\n/// | (008..006] | execBuffer   | uint16 | 2     | Tx fee safety buffer for message execution (in Wei) |\n/// | (006..004] | amortAttCost | uint16 | 2     | Amortized cost for attestation submission (in Wei)  |\n/// | (004..002] | etherPrice   | uint16 | 2     | Chain's Ether Price / Mainnet Ether Price (in BWAD) |\n/// | (002..000] | markup       | uint16 | 2     | Markup for the message execution (in BWAD)          |\n/// \u003e See Number.sol for more details on `Number` type and BWAD (binary WAD) math.\n///\n/// ## ChainGas stack layout (from highest bits to lowest)\n///\n/// | Position   | Field   | Type   | Bytes | Description      |\n/// | ---------- | ------- | ------ | ----- | ---------------- |\n/// | (016..004] | gasData | uint96 | 12    | Chain's gas data |\n/// | (004..000] | domain  | uint32 | 4     | Chain's domain   |\nlibrary GasDataLib {\n    /// @dev Amount of bits to shift to gasPrice field\n    uint96 private constant SHIFT_GAS_PRICE = 10 * 8;\n    /// @dev Amount of bits to shift to dataPrice field\n    uint96 private constant SHIFT_DATA_PRICE = 8 * 8;\n    /// @dev Amount of bits to shift to execBuffer field\n    uint96 private constant SHIFT_EXEC_BUFFER = 6 * 8;\n    /// @dev Amount of bits to shift to amortAttCost field\n    uint96 private constant SHIFT_AMORT_ATT_COST = 4 * 8;\n    /// @dev Amount of bits to shift to etherPrice field\n    uint96 private constant SHIFT_ETHER_PRICE = 2 * 8;\n\n    /// @dev Amount of bits to shift to gasData field\n    uint128 private constant SHIFT_GAS_DATA = 4 * 8;\n\n    // ═════════════════════════════════════════════════ GAS DATA ══════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded GasData struct with the given fields.\n    /// @param gasPrice_        Gas price for the chain (in Wei per gas unit)\n    /// @param dataPrice_       Calldata price (in Wei per byte of content)\n    /// @param execBuffer_      Tx fee safety buffer for message execution (in Wei)\n    /// @param amortAttCost_    Amortized cost for attestation submission (in Wei)\n    /// @param etherPrice_      Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n    /// @param markup_          Markup for the message execution (in BWAD)\n    function encodeGasData(\n        Number gasPrice_,\n        Number dataPrice_,\n        Number execBuffer_,\n        Number amortAttCost_,\n        Number etherPrice_,\n        Number markup_\n    ) internal pure returns (GasData) {\n        // Number type wraps uint16, so could safely be casted to uint96\n        // forgefmt: disable-next-item\n        return GasData.wrap(\n            uint96(Number.unwrap(gasPrice_)) \u003c\u003c SHIFT_GAS_PRICE |\n            uint96(Number.unwrap(dataPrice_)) \u003c\u003c SHIFT_DATA_PRICE |\n            uint96(Number.unwrap(execBuffer_)) \u003c\u003c SHIFT_EXEC_BUFFER |\n            uint96(Number.unwrap(amortAttCost_)) \u003c\u003c SHIFT_AMORT_ATT_COST |\n            uint96(Number.unwrap(etherPrice_)) \u003c\u003c SHIFT_ETHER_PRICE |\n            uint96(Number.unwrap(markup_))\n        );\n    }\n\n    /// @notice Wraps padded uint256 value into GasData struct.\n    function wrapGasData(uint256 paddedGasData) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(paddedGasData));\n    }\n\n    /// @notice Returns the gas price, in Wei per gas unit.\n    function gasPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_GAS_PRICE));\n    }\n\n    /// @notice Returns the calldata price, in Wei per byte of content.\n    function dataPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_DATA_PRICE));\n    }\n\n    /// @notice Returns the tx fee safety buffer for message execution, in Wei.\n    function execBuffer(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_EXEC_BUFFER));\n    }\n\n    /// @notice Returns the amortized cost for attestation submission, in Wei.\n    function amortAttCost(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_AMORT_ATT_COST));\n    }\n\n    /// @notice Returns the ratio of Chain's Ether Price / Mainnet Ether Price, in BWAD math.\n    function etherPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_ETHER_PRICE));\n    }\n\n    /// @notice Returns the markup for the message execution, in BWAD math.\n    function markup(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data)));\n    }\n\n    // ════════════════════════════════════════════════ CHAIN DATA ═════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded ChainGas struct with the given fields.\n    /// @param gasData_ Chain's gas data\n    /// @param domain_  Chain's domain\n    function encodeChainGas(GasData gasData_, uint32 domain_) internal pure returns (ChainGas) {\n        // GasData type wraps uint96, so could safely be casted to uint128\n        return ChainGas.wrap(uint128(GasData.unwrap(gasData_)) \u003c\u003c SHIFT_GAS_DATA | uint128(domain_));\n    }\n\n    /// @notice Wraps padded uint256 value into ChainGas struct.\n    function wrapChainGas(uint256 paddedChainGas) internal pure returns (ChainGas) {\n        // Casting to uint128 will truncate the highest bits, which is the behavior we want\n        return ChainGas.wrap(uint128(paddedChainGas));\n    }\n\n    /// @notice Returns the chain's gas data.\n    function gasData(ChainGas data) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(ChainGas.unwrap(data) \u003e\u003e SHIFT_GAS_DATA));\n    }\n\n    /// @notice Returns the chain's domain.\n    function domain(ChainGas data) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(ChainGas.unwrap(data));\n    }\n\n    /// @notice Returns the hash for the list of ChainGas structs.\n    function snapGasHash(ChainGas[] memory snapGas) internal pure returns (bytes32 snapGasHash_) {\n        // Use assembly to calculate the hash of the array without copying it\n        // ChainGas takes a single word of storage, thus ChainGas[] is stored in the following way:\n        // 0x00: length of the array, in words\n        // 0x20: first ChainGas struct\n        // 0x40: second ChainGas struct\n        // And so on...\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Find the location where the array data starts, we add 0x20 to skip the length field\n            let loc := add(snapGas, 0x20)\n            // Load the length of the array (in words).\n            // Shifting left 5 bits is equivalent to multiplying by 32: this converts from words to bytes.\n            let len := shl(5, mload(snapGas))\n            // Calculate the hash of the array\n            snapGasHash_ := keccak256(loc, len)\n        }\n    }\n}\n\n// contracts/libs/stack/Header.sol\n\n/// Header is encoded data with \"general routing information\".\ntype Header is uint136;\n\nusing HeaderLib for Header global;\n\n/// Types of messages supported by Origin-Destination\n/// - Base: message sent by protocol user, contains tips\n/// - Manager: message sent between AgentManager contracts located on different chains, no tips\nenum MessageFlag {\n    Base,\n    Manager\n}\n\nusing HeaderLib for MessageFlag global;\n\n/// Library for formatting _the header part_ of _the messages used by Origin and Destination_.\n/// - Header represents general information for routing a Message for Origin and Destination.\n/// - Header occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n///\n/// # Header stack layout (from highest bits to lowest)\n///\n/// | Position   | Field            | Type   | Bytes | Description                             |\n/// | ---------- | ---------------- | ------ | ----- | --------------------------------------- |\n/// | (017..016] | flag             | uint8  | 1     | Flag specifying the type of message     |\n/// | (016..012] | origin           | uint32 | 4     | Domain where message originated         |\n/// | (012..008] | nonce            | uint32 | 4     | Message nonce on the origin domain      |\n/// | (008..004] | destination      | uint32 | 4     | Domain where message will be executed   |\n/// | (004..000] | optimisticPeriod | uint32 | 4     | Optimistic period that will be enforced |\nlibrary HeaderLib {\n    /// @dev Amount of bits to shift to flag field\n    uint136 private constant SHIFT_FLAG = 16 * 8;\n    /// @dev Amount of bits to shift to origin field\n    uint136 private constant SHIFT_ORIGIN = 12 * 8;\n    /// @dev Amount of bits to shift to nonce field\n    uint136 private constant SHIFT_NONCE = 8 * 8;\n    /// @dev Amount of bits to shift to destination field\n    uint136 private constant SHIFT_DESTINATION = 4 * 8;\n\n    /// @notice Returns an encoded header with provided fields\n    /// @param origin_              Domain of origin chain\n    /// @param nonce_               Message nonce on origin chain\n    /// @param destination_         Domain of destination chain\n    /// @param optimisticPeriod_    Optimistic period for message execution\n    function encodeHeader(\n        MessageFlag flag_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint32 destination_,\n        uint32 optimisticPeriod_\n    ) internal pure returns (Header) {\n        // All casts below are upcasts, so they are safe\n        // forgefmt: disable-next-item\n        return Header.wrap(\n            uint136(uint8(flag_)) \u003c\u003c SHIFT_FLAG |\n            uint136(origin_) \u003c\u003c SHIFT_ORIGIN |\n            uint136(nonce_) \u003c\u003c SHIFT_NONCE |\n            uint136(destination_) \u003c\u003c SHIFT_DESTINATION |\n            uint136(optimisticPeriod_)\n        );\n    }\n\n    /// @notice Checks that the header is a valid encoded header.\n    function isHeader(uint256 paddedHeader) internal pure returns (bool) {\n        // Check that flag is within range\n        return _flag(paddedHeader) \u003c= uint8(type(MessageFlag).max);\n    }\n\n    /// @notice Wraps the padded encoded request into a Header-typed value.\n    /// @dev The \"padded\" header is simply an encoded header casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded headers\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedHeader) internal pure returns (Header) {\n        // Check that flag is within range\n        if (!isHeader(paddedHeader)) revert FlagOutOfRange();\n        // Casting to uint136 will truncate the highest bits, which is the behavior we want\n        return Header.wrap(uint136(paddedHeader));\n    }\n\n    /// @notice Returns header's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Header header) internal pure returns (bytes32 hashedHeader) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store header in scratch space\n            mstore(0, header)\n            // Compute hash of header padded to 32 bytes\n            hashedHeader := keccak256(0, 32)\n        }\n    }\n\n    // ══════════════════════════════════════════════ HEADER SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns header's flag field\n    function flag(Header header) internal pure returns (MessageFlag) {\n        // We check that flag is within range when wrapping the header, so this cast is safe\n        return MessageFlag(_flag(Header.unwrap(header)));\n    }\n\n    /// @notice Returns header's origin field\n    function origin(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_ORIGIN);\n    }\n\n    /// @notice Returns header's nonce field\n    function nonce(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_NONCE);\n    }\n\n    /// @notice Returns header's destination field\n    function destination(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_DESTINATION);\n    }\n\n    /// @notice Returns header's optimistic seconds field\n    function optimisticPeriod(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns header's flag field without casting to MessageFlag\n    function _flag(uint256 paddedHeader) private pure returns (uint8) {\n        // Casting to uint8 will truncate the highest bits, which is the behavior we want\n        return uint8(paddedHeader \u003e\u003e SHIFT_FLAG);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n     * constructor.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall \u0026\u0026 _initialized \u003c 1) || (!AddressUpgradeable.isContract(address(this)) \u0026\u0026 _initialized == 1),\n            \"Initializable: contract is already initialized\"\n        );\n        _initialized = 1;\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: setting the version to 255 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing \u0026\u0026 _initialized \u003c version, \"Initializable: contract is already initialized\");\n        _initialized = version;\n        _initializing = true;\n        _;\n        _initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        require(_initializing, \"Initializable: contract is not initializing\");\n        _;\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized != type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint8) {\n        return _initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _initializing;\n    }\n}\n\n// contracts/interfaces/IAgentManager.sol\n\ninterface IAgentManager {\n    /**\n     * @notice Allows Inbox to open a Dispute between a Guard and a Notary, if they are both not in Dispute already.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Guard or Notary is already in Dispute.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Allows Inbox to slash an agent, if their fraud was proven.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Domain doesn't match the saved agent domain.\n     * @param domain    Domain where the Agent is active\n     * @param agent     Address of the Agent\n     * @param prover    Address that initially provided fraud proof\n     */\n    function slashAgent(uint32 domain, address agent, address prover) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest known root of the Agent Merkle Tree.\n     */\n    function agentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns the number of opened Disputes.\n     * @dev This includes the Disputes that have been resolved already.\n     */\n    function getDisputesAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns information about the dispute with the given index.\n     * @dev Will revert if dispute with given index hasn't been opened yet.\n     * @param index             Dispute index\n     * @return guard            Address of the Guard in the Dispute\n     * @return notary           Address of the Notary in the Dispute\n     * @return slashedAgent     Address of the Agent who was slashed when Dispute was resolved\n     * @return fraudProver      Address who provided fraud proof to resolve the Dispute\n     * @return reportPayload    Raw payload with report data that led to the Dispute\n     * @return reportSignature  Guard signature for the report payload\n     */\n    function getDispute(uint256 index)\n        external\n        view\n        returns (\n            address guard,\n            address notary,\n            address slashedAgent,\n            address fraudProver,\n            bytes memory reportPayload,\n            bytes memory reportSignature\n        );\n\n    /**\n     * @notice Returns the current Dispute status of a given agent. See Structures.sol for details.\n     * @dev Every returned value will be set to zero if agent was not slashed and is not in Dispute.\n     * `rival` and `disputePtr` will be set to zero if the agent was slashed without being in Dispute.\n     * @param agent         Agent address\n     * @return flag         Flag describing the current Dispute status for the agent: None/Pending/Slashed\n     * @return rival        Address of the rival agent in the Dispute\n     * @return fraudProver  Address who provided fraud proof to resolve the Dispute\n     * @return disputePtr   Index of the opened Dispute PLUS ONE. Zero if agent is not in Dispute.\n     */\n    function disputeStatus(address agent)\n        external\n        view\n        returns (DisputeFlag flag, address rival, address fraudProver, uint256 disputePtr);\n}\n\n// contracts/interfaces/IAgentSecured.sol\n\ninterface IAgentSecured {\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * between a Guard and a Notary has been opened.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * has been resolved due to one of the agents being slashed.\n     * \u003e `rivalIndex` will be ZERO, if the slashed agent was not in the Dispute.\n     * @param slashedIndex  Index of the slashed agent in the Agent Merkle Tree\n     * @param rivalIndex    Index of the their Dispute Rival in the Agent Merkle Tree\n     */\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the address of the local AgentManager contract, which is treated as\n     * the \"source of truth\" for agent statuses.\n     */\n    function agentManager() external view returns (address);\n\n    /**\n     * @notice Returns the address of the local Inbox contract, which is treated as\n     * the \"source of truth\" for agent-signed statements.\n     * @dev Inbox passes verified agent statements to `IAgentSecured` contract.\n     */\n    function inbox() external view returns (address);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns (flag, openedAt, resolvedAt) that describes the latest status of\n     * the latest dispute for an agent with a given index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param agentIndex    Agent index in the Agent Merkle Tree\n     * @return              Latest dispute status for the given agent: (flag, openedAt, resolvedAt)\n     */\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory);\n}\n\n// contracts/libs/memory/ByteString.sol\n\n/// @dev CallData is a memory view over the payload to be used for an external call, i.e.\n/// recipient.call(callData). Its length is always (4 + 32 * N) bytes:\n/// - First 4 bytes represent the function selector.\n/// - 32 * N bytes represent N words that function arguments occupy.\ntype CallData is uint256;\n\n/// @dev Attach library functions to CallData\nusing ByteString for CallData global;\n\n/// @dev Signature is a memory view over a \"65 bytes\" array representing a ECDSA signature.\ntype Signature is uint256;\n\n/// @dev Attach library functions to Signature\nusing ByteString for Signature global;\n\nlibrary ByteString {\n    using MemViewLib for bytes;\n\n    /**\n     * @dev non-compact ECDSA signatures are enforced as of OZ 4.7.3\n     *\n     *      Signature payload memory layout\n     * [000 .. 032) r   bytes32 32 bytes\n     * [032 .. 064) s   bytes32 32 bytes\n     * [064 .. 065) v   uint8    1 byte\n     */\n    uint256 internal constant SIGNATURE_LENGTH = 65;\n    uint256 private constant OFFSET_R = 0;\n    uint256 private constant OFFSET_S = 32;\n    uint256 private constant OFFSET_V = 64;\n\n    /**\n     * @dev Calldata memory layout\n     * [000 .. 004) selector    bytes4  4 bytes\n     *      Optional: N function arguments\n     * [004 .. 036) arg1        bytes32 32 bytes\n     *      ..\n     * [AAA .. END) argN        bytes32 32 bytes\n     */\n    uint256 internal constant SELECTOR_LENGTH = 4;\n    uint256 private constant OFFSET_SELECTOR = 0;\n    uint256 private constant OFFSET_ARGUMENTS = SELECTOR_LENGTH;\n\n    // ═════════════════════════════════════════════════ SIGNATURE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the signature payload from the given values.\n     * @dev Using ByteString.formatSignature({r: r, s: s, v: v}) will make sure\n     * that params are given in the right order.\n     */\n    function formatSignature(bytes32 r, bytes32 s, uint8 v) internal pure returns (bytes memory) {\n        return abi.encodePacked(r, s, v);\n    }\n\n    /**\n     * @notice Returns a Signature view over for the given payload.\n     * @dev Will revert if the payload is not a signature.\n     */\n    function castToSignature(bytes memory payload) internal pure returns (Signature) {\n        return castToSignature(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Signature view.\n     * @dev Will revert if the memory view is not over a signature.\n     */\n    function castToSignature(MemView memView) internal pure returns (Signature) {\n        if (!isSignature(memView)) revert UnformattedSignature();\n        return Signature.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a signature\n     */\n    function isSignature(MemView memView) internal pure returns (bool) {\n        return memView.len() == SIGNATURE_LENGTH;\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Signature signature) internal pure returns (MemView) {\n        return MemView.wrap(Signature.unwrap(signature));\n    }\n\n    // ═════════════════════════════════════════════ SIGNATURE SLICING ═════════════════════════════════════════════════\n\n    /// @notice Unpacks signature payload into (r, s, v) parameters.\n    /// @dev Make sure to verify signature length with isSignature() beforehand.\n    function toRSV(Signature signature) internal pure returns (bytes32 r, bytes32 s, uint8 v) {\n        // Get the underlying memory view\n        MemView memView = unwrap(signature);\n        r = memView.index({index_: OFFSET_R, bytes_: 32});\n        s = memView.index({index_: OFFSET_S, bytes_: 32});\n        // Can be safely casted to uint8, since we index a single byte\n        v = uint8(memView.indexUint({index_: OFFSET_V, bytes_: 1}));\n    }\n\n    // ═════════════════════════════════════════════════ CALLDATA ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the calldata with the modified arguments:\n     * the existing arguments are prepended with the arguments from the prefix.\n     * @dev Given:\n     *  - `calldata = abi.encodeWithSelector(foo.selector, d, e);`\n     *  - `prefix = abi.encode(a, b, c);`\n     *  - `a`, `b`, `c` are arguments of static type (i.e. not dynamically sized ones)\n     *      Then:\n     *  - Function will return abi.encodeWithSelector(foo.selector, a, c, c, d, e)\n     *  - Returned calldata will trigger `foo(a, b, c, d, e)` when used for a contract call.\n     * Note: for clarification as to what types are considered static, see\n     * https://docs.soliditylang.org/en/latest/abi-spec.html#formal-specification-of-the-encoding\n     * @param callData  Calldata that needs to be modified\n     * @param prefix    ABI-encoded arguments to use as the first arguments in the new calldata\n     * @return Modified calldata having prefix as the first arguments.\n     */\n    function addPrefix(CallData callData, bytes memory prefix) internal view returns (bytes memory) {\n        // Prefix should occupy a whole amount of words in memory\n        if (!_fullWords(prefix.length)) revert UnformattedCallDataPrefix();\n        MemView[] memory views = new MemView[](3);\n        // Use payload's function selector\n        views[0] = abi.encodePacked(callData.callSelector()).ref();\n        // Use prefix as the first arguments\n        views[1] = prefix.ref();\n        // Use payload's remaining arguments\n        views[2] = callData.arguments();\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a CallData view over for the given payload.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(bytes memory payload) internal pure returns (CallData) {\n        return castToCallData(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a CallData view.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(MemView memView) internal pure returns (CallData) {\n        if (!isCallData(memView)) revert UnformattedCallData();\n        return CallData.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a valid calldata, i.e.\n     * a function selector, followed by arbitrary amount of arguments.\n     */\n    function isCallData(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Calldata should at least have a function selector\n        if (length \u003c SELECTOR_LENGTH) return false;\n        // The remainder of the calldata should be exactly N memory words (N \u003e= 0)\n        return _fullWords(length - SELECTOR_LENGTH);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(CallData callData) internal pure returns (MemView) {\n        return MemView.wrap(CallData.unwrap(callData));\n    }\n\n    /// @notice Returns callData's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(CallData callData) internal pure returns (bytes32) {\n        return callData.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ CALLDATA SLICING ══════════════════════════════════════════════════\n\n    /**\n     * @notice Returns amount of memory words (32 byte chunks) the function arguments\n     * occupy in the calldata.\n     * @dev This might differ from amount of arguments supplied, if any of the arguments\n     * occupies more than one memory slot. It is true, however, that argument part of the payload\n     * occupies exactly N words, even for dynamic types like `bytes`\n     */\n    function argumentWords(CallData callData) internal pure returns (uint256) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        // Equivalent of (length - SELECTOR_LENGTH) / 32\n        return (memView.len() - SELECTOR_LENGTH) \u003e\u003e 5;\n    }\n\n    /// @notice Returns selector for the provided calldata.\n    function callSelector(CallData callData) internal pure returns (bytes4) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return bytes4(memView.index({index_: OFFSET_SELECTOR, bytes_: SELECTOR_LENGTH}));\n    }\n\n    /// @notice Returns abi encoded arguments for the provided calldata.\n    function arguments(CallData callData) internal pure returns (MemView) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return memView.sliceFrom({index_: OFFSET_ARGUMENTS});\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if length is full amount of memory words (32 bytes).\n    function _fullWords(uint256 length) internal pure returns (bool) {\n        // The equivalent of length % 32 == 0\n        return length \u0026 31 == 0;\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n    function __Context_init() internal onlyInitializing {\n    }\n\n    function __Context_init_unchained() internal onlyInitializing {\n    }\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[50] private __gap;\n}\n\n// contracts/libs/merkle/MerkleTree.sol\n\n/// `BaseTree` is a struct representing incremental merkle tree.\n/// - Contains only the current branch.\n/// - The number of inserted leaves is stored externally, and is later supplied for tree operations.\n/// - Has a fixed height of `ORIGIN_TREE_HEIGHT`.\n/// - Can store up to `2 ** ORIGIN_TREE_HEIGHT - 1` leaves.\n/// \u003e Note: the hash function for the tree `H(x, y)` is defined as:\n/// \u003e - `H(0,0) = 0`\n/// \u003e - `H(x,y) = keccak256(x, y), when (x != 0 || y != 0)`\n/// ## Invariant for leafs\n/// - The leftmost empty leaf has `index == count`, where `count` is the amount of the inserted leafs so far.\n/// - Value for any empty leaf or node is bytes32(0).\n/// ## Invariant for current branch\n/// `branch[i]` is always the value of a node on the i-th level.\n/// Levels are numbered from leafs to root: `0 .. ORIGIN_TREE_HEIGHT`.\n/// `branch[i]` stores the value for the node, such that:\n//  - The node is a \"left child\" (e.g. has an even index).\n/// - The node must have two non-empty children.\n/// - Out of all level's \"left child\" nodes with \"non-empty children\",\n/// the one with the biggest index (the rightmost one) is stored as `branch[i]`.\n/// \u003e __`branch` could be used to form a proof of inclusion for the first empty leaf (`index == count`).__\n/// _Here is how:_\n/// - Let's walk along the path from the \"first empty leaf\" to the root.\n/// - i-th bit of the \"first empty leaf\" index (which is equal to `count`) determines if the path's node\n/// for this i-th level is a \"left child\" or a \"right child\".\n/// - i-th bit in `count` is 0 → we are the left child on this level → sibling is the right child\n/// that does not exist yet → `proof[i] = bytes32(0)`.\n/// - i-th bit in `count` is 1 → we are the right child on this level → sibling is the left child\n/// sibling is the rightmost \"left child\" node on the level → `proof[i] = branch[i]`.\n/// \u003e Therefore `proof[i] = (count \u0026 (1 \u003c\u003c i)) == 0 ? bytes32(0) : branch[i])`\nstruct BaseTree {\n    bytes32[ORIGIN_TREE_HEIGHT] branch;\n}\n\nusing MerkleTree for BaseTree global;\n\n/// `HistoricalTree` is an incremental merkle tree keeping track of its historical merkle roots.\n/// \u003e - `roots[N]` is the root of the tree after `N` leafs were inserted\n/// \u003e - `roots[0] == bytes32(0)`\n/// @param tree     Incremental merkle tree\n/// @param roots    Historical merkle roots of the tree\nstruct HistoricalTree {\n    BaseTree tree;\n    bytes32[] roots;\n}\n\nusing MerkleTree for HistoricalTree global;\n\n/// `DynamicTree` is a struct representing a Merkle Tree with `2**AGENT_TREE_HEIGHT` leaves.\n/// - A single operation is available: update value for leaf with an arbitrary index (which might be a non-empty leaf).\n/// - This is done by requesting the proof of inclusion for the old value, which is used to both\n/// verify the old value, and calculate the new root.\n/// \u003e Based on Original idea from [ER forum post](https://ethresear.ch/t/efficient-on-chain-dynamic-merkle-tree/11054).\nstruct DynamicTree {\n    bytes32 root;\n}\n\nusing MerkleTree for DynamicTree global;\n\n/// MerkleTree is work based on Nomad's Merkle.sol, which is used under MIT OR Apache-2.0\n/// [link](https://github.com/nomad-xyz/monorepo/blob/main/packages/contracts-core/contracts/libs/Merkle.sol).\n/// With the following changes:\n/// - Adapted for Solidity 0.8.x.\n/// - Amount of tree leaves stored externally.\n/// - Added thorough documentation.\n/// - `H(0,0) = 0` optimization from [ER forum post](https://ethresear.ch/t/optimizing-sparse-merkle-trees/3751/6).\n/// \u003e Nomad's Merkle.sol is work based on eth2 deposit contract, which is used under CC0-1.0\n///[link](https://github.com/ethereum/deposit_contract/blob/dev/deposit_contract/contracts/validator_registration.v.py).\n/// With the following changes:\n/// \u003e - Implemented in Solidity 0.7.6 (eth2 deposit contract implemented in Vyper).\n/// \u003e - `H() = keccak256()` is used as the hashing function instead of `sha256()`.\nlibrary MerkleTree {\n    /// @dev For root calculation we need at least one empty leaf, thus the minus one in the formula.\n    uint256 internal constant MAX_LEAVES = 2 ** ORIGIN_TREE_HEIGHT - 1;\n\n    // ═════════════════════════════════════════════════ BASE TREE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Inserts `node` into merkle tree\n     * @dev Reverts if tree is full\n     * @param newCount  Amount of inserted leaves in the tree after the insertion (i.e. current + 1)\n     * @param node      Element to insert into tree\n     */\n    function insertBase(BaseTree storage tree, uint256 newCount, bytes32 node) internal {\n        if (newCount \u003e MAX_LEAVES) revert MerkleTreeFull();\n        // We go up the tree following the branch from the empty leaf AFTER the just inserted one.\n        // We stop when we find the first \"right child\" node.\n        // Its sibling is now the rightmost \"left child\" node that has two non-empty children.\n        // Therefore we need to update `tree.branch` value on this level.\n        // One could see that `tree.branch` value on lower and higher levels remain unchanged.\n\n        // Loop invariant: `node` is the current level's value for the branch from JUST INSERTED leaf\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            if ((newCount \u0026 1) == 1) {\n                // Found the first \"right child\" node on the branch from EMPTY leaf\n                // `node` is the value for node on branch from JUST INSERTED leaf\n                // Which in this case is the \"left child\".\n                // We update tree.branch and exit\n                tree.branch[i] = node;\n                return;\n            }\n            // On the branch from EMPTY leaf this is still a \"left child\".\n            // Meaning on branch from JUST INSERTED leaf, `node` is a right child.\n            // We compute value for `node` parent using `tree.branch` invariant:\n            // This is the rightmost \"left child\" node, which would be sibling of `node`.\n            node = MerkleMath.getParent(tree.branch[i], node);\n            // Get the parent index, and go to the next tree level\n            newCount \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n        // As the loop should always end prematurely with the `return` statement,\n        // this code should be unreachable. We assert `false` just to be safe.\n        assert(false);\n    }\n\n    /**\n     * @notice Calculates and returns current root of the merkle tree.\n     * @param count     Current amount of inserted leaves in the tree\n     * @return current  Calculated root of `tree`\n     */\n    function rootBase(BaseTree storage tree, uint256 count) internal view returns (bytes32 current) {\n        // To calculate the root we follow the branch of first EMPTY leaf (index == count)\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            // Check if we are the left or the right child on the current level\n            if ((count \u0026 1) == 1) {\n                // We are the right child. Our sibling is the \"rightmost\" \"left-child\" node\n                // that has two non-empty children → sibling is `tree.branch[i]`\n                current = MerkleMath.getParent(tree.branch[i], current);\n            } else {\n                // We are the left child. Our sibling does not exist yet → sibling is EMPTY\n                current = MerkleMath.getParent(current, bytes32(0));\n            }\n            // Get the parent index, and go to the next tree level\n            count \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    // ══════════════════════════════════════════════ HISTORICAL TREE ══════════════════════════════════════════════════\n\n    /// @notice Initializes the historical roots for the tree by inserting an empty root.\n    // solhint-disable-next-line ordering\n    function initializeRoots(HistoricalTree storage tree) internal returns (bytes32 savedRoot) {\n        // This should only be called once, when the contract is initialized\n        assert(tree.roots.length == 0);\n        // Save root for empty merkle tree: bytes32(0)\n        tree.roots.push(savedRoot);\n    }\n\n    /// @notice Inserts a new leaf into the merkle tree.\n    /// @dev Reverts if tree is full.\n    /// @param node         Element to insert into tree\n    /// @return newRoot     Merkle root after the leaf was inserted\n    function insert(HistoricalTree storage tree, bytes32 node) internal returns (bytes32 newRoot) {\n        // Tree count after the new leaf will be inserted (we store roots[0] as root of empty tree)\n        uint256 newCount = tree.roots.length;\n        tree.tree.insertBase(newCount, node);\n        // Save the new root\n        newRoot = tree.tree.rootBase(newCount);\n        tree.roots.push(newRoot);\n    }\n\n    /// @notice Returns the historical root of the merkle tree.\n    /// @dev Reverts if not enough leafs have been inserted.\n    /// @param count            Amount of leafs in the tree at some point of time\n    /// @return historicalRoot  Merkle root after `count` leafs were inserted\n    function root(HistoricalTree storage tree, uint256 count) internal view returns (bytes32 historicalRoot) {\n        if (count \u003e= tree.roots.length) revert NotEnoughLeafs();\n        return tree.roots[count];\n    }\n\n    // ═══════════════════════════════════════════════ DYNAMIC TREE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Updates the value for the leaf with the given index in the Dynamic Merkle Tree.\n     * @dev Will revert if incorrect proof of inclusion for old value is supplied.\n     * @param tree          Dynamic merkle tree\n     * @param index         Index of the leaf to update\n     * @param oldValue      Previous value of the leaf\n     * @param branch        Proof of inclusion of previous value into the tree\n     * @param newValue      New leaf value to assign\n     * @return newRoot      New value for the Merkle Root after the leaf is updated\n     */\n    function update(\n        DynamicTree storage tree,\n        uint256 index,\n        bytes32 oldValue,\n        bytes32[] memory branch,\n        bytes32 newValue\n    ) internal returns (bytes32 newRoot) {\n        // Check that the old value + proof result in a correct root\n        if (MerkleMath.proofRoot(index, oldValue, branch, AGENT_TREE_HEIGHT) != tree.root) {\n            revert LeafNotProven();\n        }\n        // New root is new value + the same proof (values for sibling nodes are not updated)\n        newRoot = MerkleMath.proofRoot(index, newValue, branch, AGENT_TREE_HEIGHT);\n        // Write the new root\n        tree.root = newRoot;\n    }\n}\n\n// contracts/libs/stack/Tips.sol\n\n/// Tips is encoded data with \"tips paid for sending a base message\".\n/// Note: even though uint256 is also an underlying type for MemView, Tips is stored ON STACK.\ntype Tips is uint256;\n\nusing TipsLib for Tips global;\n\n/// # Tips\n/// Library for formatting _the tips part_ of _the base messages_.\n///\n/// ## How the tips are awarded\n/// Tips are paid for sending a base message, and are split across all the agents that\n/// made the message execution on destination chain possible.\n/// ### Summit tips\n/// Split between:\n///     - Guard posting a snapshot with state ST_G for the origin chain.\n///     - Notary posting a snapshot SN_N using ST_G. This creates attestation A.\n///     - Notary posting a message receipt after it is executed on destination chain.\n/// ### Attestation tips\n/// Paid to:\n///     - Notary posting attestation A to destination chain.\n/// ### Execution tips\n/// Paid to:\n///     - First executor performing a valid execution attempt (correct proofs, optimistic period over),\n///      using attestation A to prove message inclusion on origin chain, whether the recipient reverted or not.\n/// ### Delivery tips.\n/// Paid to:\n///     - Executor who successfully executed the message on destination chain.\n///\n/// ## Tips encoding\n/// - Tips occupy a single storage word, and thus are stored on stack instead of being stored in memory.\n/// - The actual tip values should be determined by multiplying stored values by divided by TIPS_MULTIPLIER=2**32.\n/// - Tips are packed into a single word of storage, while allowing real values up to ~8*10**28 for every tip category.\n/// \u003e The only downside is that the \"real tip values\" are now multiplies of ~4*10**9, which should be fine even for\n/// the chains with the most expensive gas currency.\n/// # Tips stack layout (from highest bits to lowest)\n///\n/// | Position   | Field          | Type   | Bytes | Description                                                |\n/// | ---------- | -------------- | ------ | ----- | ---------------------------------------------------------- |\n/// | (032..024] | summitTip      | uint64 | 8     | Tip for agents interacting with Summit contract            |\n/// | (024..016] | attestationTip | uint64 | 8     | Tip for Notary posting attestation to Destination contract |\n/// | (016..008] | executionTip   | uint64 | 8     | Tip for valid execution attempt on destination chain       |\n/// | (008..000] | deliveryTip    | uint64 | 8     | Tip for successful message delivery on destination chain   |\n\nlibrary TipsLib {\n    using SafeCast for uint256;\n\n    /// @dev Amount of bits to shift to summitTip field\n    uint256 private constant SHIFT_SUMMIT_TIP = 24 * 8;\n    /// @dev Amount of bits to shift to attestationTip field\n    uint256 private constant SHIFT_ATTESTATION_TIP = 16 * 8;\n    /// @dev Amount of bits to shift to executionTip field\n    uint256 private constant SHIFT_EXECUTION_TIP = 8 * 8;\n\n    // ═══════════════════════════════════════════════════ TIPS ════════════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips with the given fields\n    /// @param summitTip_        Tip for agents interacting with Summit contract, divided by TIPS_MULTIPLIER\n    /// @param attestationTip_   Tip for Notary posting attestation to Destination contract, divided by TIPS_MULTIPLIER\n    /// @param executionTip_     Tip for valid execution attempt on destination chain, divided by TIPS_MULTIPLIER\n    /// @param deliveryTip_      Tip for successful message delivery on destination chain, divided by TIPS_MULTIPLIER\n    function encodeTips(uint64 summitTip_, uint64 attestationTip_, uint64 executionTip_, uint64 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // forgefmt: disable-next-item\n        return Tips.wrap(\n            uint256(summitTip_) \u003c\u003c SHIFT_SUMMIT_TIP |\n            uint256(attestationTip_) \u003c\u003c SHIFT_ATTESTATION_TIP |\n            uint256(executionTip_) \u003c\u003c SHIFT_EXECUTION_TIP |\n            uint256(deliveryTip_)\n        );\n    }\n\n    /// @notice Convenience function to encode tips with uint256 values.\n    function encodeTips256(uint256 summitTip_, uint256 attestationTip_, uint256 executionTip_, uint256 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // In practice, the tips amounts are not supposed to be higher than 2**96, and with 32 bits of granularity\n        // using uint64 is enough to store the values. However, we still check for overflow just in case.\n        // TODO: consider using Number type to store the tips values.\n        return encodeTips({\n            summitTip_: (summitTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            attestationTip_: (attestationTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            executionTip_: (executionTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            deliveryTip_: (deliveryTip_ \u003e\u003e TIPS_GRANULARITY).toUint64()\n        });\n    }\n\n    /// @notice Wraps the padded encoded tips into a Tips-typed value.\n    /// @dev There is no actual padding here, as the underlying type is already uint256,\n    /// but we include this function for consistency and to be future-proof, if tips will eventually use anything\n    /// smaller than uint256.\n    function wrapPadded(uint256 paddedTips) internal pure returns (Tips) {\n        return Tips.wrap(paddedTips);\n    }\n\n    /**\n     * @notice Returns a formatted Tips payload specifying empty tips.\n     * @return Formatted tips\n     */\n    function emptyTips() internal pure returns (Tips) {\n        return Tips.wrap(0);\n    }\n\n    /// @notice Returns tips's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Tips tips) internal pure returns (bytes32 hashedTips) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store tips in scratch space\n            mstore(0, tips)\n            // Compute hash of tips padded to 32 bytes\n            hashedTips := keccak256(0, 32)\n        }\n    }\n\n    // ═══════════════════════════════════════════════ TIPS SLICING ════════════════════════════════════════════════════\n\n    /// @notice Returns summitTip field\n    function summitTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_SUMMIT_TIP);\n    }\n\n    /// @notice Returns attestationTip field\n    function attestationTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_ATTESTATION_TIP);\n    }\n\n    /// @notice Returns executionTip field\n    function executionTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_EXECUTION_TIP);\n    }\n\n    /// @notice Returns deliveryTip field\n    function deliveryTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips));\n    }\n\n    // ════════════════════════════════════════════════ TIPS VALUE ═════════════════════════════════════════════════════\n\n    /// @notice Returns total value of the tips payload.\n    /// This is the sum of the encoded values, scaled up by TIPS_MULTIPLIER\n    function value(Tips tips) internal pure returns (uint256 value_) {\n        value_ = uint256(tips.summitTip()) + tips.attestationTip() + tips.executionTip() + tips.deliveryTip();\n        value_ \u003c\u003c= TIPS_GRANULARITY;\n    }\n\n    /// @notice Increases the delivery tip to match the new value.\n    function matchValue(Tips tips, uint256 newValue) internal pure returns (Tips newTips) {\n        uint256 oldValue = tips.value();\n        if (newValue \u003c oldValue) revert TipsValueTooLow();\n        // We want to increase the delivery tip, while keeping the other tips the same\n        unchecked {\n            uint256 delta = (newValue - oldValue) \u003e\u003e TIPS_GRANULARITY;\n            // `delta` fits into uint224, as TIPS_GRANULARITY is 32, so this never overflows uint256.\n            // In practice, this will never overflow uint64 as well, but we still check it just in case.\n            if (delta + tips.deliveryTip() \u003e type(uint64).max) revert TipsOverflow();\n            // Delivery tips occupy lowest 8 bytes, so we can just add delta to the tips value\n            // to effectively increase the delivery tip (knowing that delta fits into uint64).\n            newTips = Tips.wrap(Tips.unwrap(tips) + delta);\n        }\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    function __Ownable_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable_init_unchained() internal onlyInitializing {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n    function __Ownable2Step_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable2Step_init_unchained() internal onlyInitializing {\n    }\n    address private _pendingOwner;\n\n    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Returns the address of the pending owner.\n     */\n    function pendingOwner() public view virtual returns (address) {\n        return _pendingOwner;\n    }\n\n    /**\n     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual override onlyOwner {\n        _pendingOwner = newOwner;\n        emit OwnershipTransferStarted(owner(), newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual override {\n        delete _pendingOwner;\n        super._transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev The new owner accepts the ownership transfer.\n     */\n    function acceptOwnership() public virtual {\n        address sender = _msgSender();\n        require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n        _transferOwnership(sender);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// contracts/libs/memory/State.sol\n\n/// State is a memory view over a formatted state payload.\ntype State is uint256;\n\nusing StateLib for State global;\n\n/// # State\n/// State structure represents the state of Origin contract at some point of time.\n/// - State is structured in a way to track the updates of the Origin Merkle Tree.\n/// - State includes root of the Origin Merkle Tree, origin domain and some additional metadata.\n/// ## Origin Merkle Tree\n/// Hash of every sent message is inserted in the Origin Merkle Tree, which changes\n/// the value of Origin Merkle Root (which is the root for the mentioned tree).\n/// - Origin has a single Merkle Tree for all messages, regardless of their destination domain.\n/// - This leads to Origin state being updated if and only if a message was sent in a block.\n/// - Origin contract is a \"source of truth\" for states: a state is considered \"valid\" in its Origin,\n/// if it matches the state of the Origin contract after the N-th (nonce) message was sent.\n///\n/// # Memory layout of State fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                    |\n/// | ---------- | ----------- | ------- | ----- | ------------------------------ |\n/// | [000..032) | root        | bytes32 | 32    | Root of the Origin Merkle Tree |\n/// | [032..036) | origin      | uint32  | 4     | Domain where Origin is located |\n/// | [036..040) | nonce       | uint32  | 4     | Amount of sent messages        |\n/// | [040..045) | blockNumber | uint40  | 5     | Block of last sent message     |\n/// | [045..050) | timestamp   | uint40  | 5     | Time of last sent message      |\n/// | [050..062) | gasData     | uint96  | 12    | Gas data for the chain         |\n///\n/// @dev State could be used to form a Snapshot to be signed by a Guard or a Notary.\nlibrary StateLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_ROOT = 0;\n    uint256 private constant OFFSET_ORIGIN = 32;\n    uint256 private constant OFFSET_NONCE = 36;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 40;\n    uint256 private constant OFFSET_TIMESTAMP = 45;\n    uint256 private constant OFFSET_GAS_DATA = 50;\n\n    // ═══════════════════════════════════════════════════ STATE ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted State payload with provided fields\n     * @param root_         New merkle root\n     * @param origin_       Domain of Origin's chain\n     * @param nonce_        Nonce of the merkle root\n     * @param blockNumber_  Block number when root was saved in Origin\n     * @param timestamp_    Block timestamp when root was saved in Origin\n     * @param gasData_      Gas data for the chain\n     * @return Formatted state\n     */\n    function formatState(\n        bytes32 root_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_,\n        GasData gasData_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(root_, origin_, nonce_, blockNumber_, timestamp_, gasData_);\n    }\n\n    /**\n     * @notice Returns a State view over the given payload.\n     * @dev Will revert if the payload is not a state.\n     */\n    function castToState(bytes memory payload) internal pure returns (State) {\n        return castToState(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a State view.\n     * @dev Will revert if the memory view is not over a state.\n     */\n    function castToState(MemView memView) internal pure returns (State) {\n        if (!isState(memView)) revert UnformattedState();\n        return State.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted State.\n    function isState(MemView memView) internal pure returns (bool) {\n        return memView.len() == STATE_LENGTH;\n    }\n\n    /// @notice Returns the hash of a State, that could be later signed by a Guard to signal\n    /// that the state is invalid.\n    function hashInvalid(State state) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(stateInvalidSalt, keccak(state))\n        return state.unwrap().keccakSalted(STATE_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(State state) internal pure returns (MemView) {\n        return MemView.wrap(State.unwrap(state));\n    }\n\n    /// @notice Compares two State structures.\n    function equals(State a, State b) internal pure returns (bool) {\n        // Length of a State payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═══════════════════════════════════════════════ STATE HASHING ═══════════════════════════════════════════════════\n\n    /// @notice Returns the hash of the State.\n    /// @dev We are using the Merkle Root of a tree with two leafs (see below) as state hash.\n    function leaf(State state) internal pure returns (bytes32) {\n        (bytes32 leftLeaf_, bytes32 rightLeaf_) = state.subLeafs();\n        // Final hash is the parent of these leafs\n        return keccak256(bytes.concat(leftLeaf_, rightLeaf_));\n    }\n\n    /// @notice Returns \"sub-leafs\" of the State. Hash of these \"sub leafs\" is going to be used\n    /// as a \"state leaf\" in the \"Snapshot Merkle Tree\".\n    /// This enables proving that leftLeaf = (root, origin) was a part of the \"Snapshot Merkle Tree\",\n    /// by combining `rightLeaf` with the remainder of the \"Snapshot Merkle Proof\".\n    function subLeafs(State state) internal pure returns (bytes32 leftLeaf_, bytes32 rightLeaf_) {\n        MemView memView = state.unwrap();\n        // Left leaf is (root, origin)\n        leftLeaf_ = memView.prefix({len_: OFFSET_NONCE}).keccak();\n        // Right leaf is (metadata), or (nonce, blockNumber, timestamp)\n        rightLeaf_ = memView.sliceFrom({index_: OFFSET_NONCE}).keccak();\n    }\n\n    /// @notice Returns the left \"sub-leaf\" of the State.\n    function leftLeaf(bytes32 root_, uint32 origin_) internal pure returns (bytes32) {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(root_, origin_));\n    }\n\n    /// @notice Returns the right \"sub-leaf\" of the State.\n    function rightLeaf(uint32 nonce_, uint40 blockNumber_, uint40 timestamp_, GasData gasData_)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(nonce_, blockNumber_, timestamp_, gasData_));\n    }\n\n    // ═══════════════════════════════════════════════ STATE SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns a historical Merkle root from the Origin contract.\n    function root(State state) internal pure returns (bytes32) {\n        return state.unwrap().index({index_: OFFSET_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns domain of chain where the Origin contract is deployed.\n    function origin(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns nonce of Origin contract at the time, when `root` was the Merkle root.\n    function nonce(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when `root` was saved in Origin.\n    function blockNumber(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when `root` was saved in Origin.\n    /// @dev This is the timestamp according to the origin chain.\n    function timestamp(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n\n    /// @notice Returns gas data for the chain.\n    function gasData(State state) internal pure returns (GasData) {\n        return GasDataLib.wrapGasData(state.unwrap().indexUint({index_: OFFSET_GAS_DATA, bytes_: GAS_DATA_LENGTH}));\n    }\n}\n\n// contracts/libs/memory/BaseMessage.sol\n\n/// BaseMessage is a memory view over the base message supported by Origin-Destination\ntype BaseMessage is uint256;\n\nusing BaseMessageLib for BaseMessage global;\n\n/// BaseMessage structure represents a base message sent via the Origin-Destination contracts.\n/// - It only contains data relevant to the base message, the rest of data is encoded in the message header.\n/// - `sender` and `recipient` for EVM chains are EVM addresses casted to bytes32, while preserving left-alignment.\n/// - `tips` and `request` parameters are specified by a message sender\n/// \u003e Origin will calculate minimum tips for given request and content length, and will reject messages with tips\n/// lower than that.\n///\n/// # Memory layout of BaseMessage fields\n///\n/// | Position   | Field     | Type    | Bytes | Description                            |\n/// | ---------- | --------- | ------- | ----- | -------------------------------------- |\n/// | [000..032) | tips      | uint256 | 32    | Encoded tips paid on origin chain      |\n/// | [032..064) | sender    | bytes32 | 32    | Sender address on origin chain         |\n/// | [064..096) | recipient | bytes32 | 32    | Recipient address on destination chain |\n/// | [096..116) | request   | uint160 | 20    | Encoded request for message execution  |\n/// | [104..AAA) | content   | bytes   | ??    | Content to be passed to recipient      |\nlibrary BaseMessageLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_TIPS = 0;\n    uint256 private constant OFFSET_SENDER = 32;\n    uint256 private constant OFFSET_RECIPIENT = 64;\n    uint256 private constant OFFSET_REQUEST = OFFSET_RECIPIENT + TIPS_LENGTH;\n    uint256 private constant OFFSET_CONTENT = OFFSET_REQUEST + REQUEST_LENGTH;\n\n    // ═══════════════════════════════════════════════ BASE MESSAGE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted BaseMessage payload with provided fields.\n     * @param tips_         Encoded tips information\n     * @param sender_       Sender address on origin chain\n     * @param recipient_    Recipient address on destination chain\n     * @param request_      Encoded request for message execution\n     * @param content_      Raw content to be passed to recipient on destination chain\n     * @return Formatted base message\n     */\n    function formatBaseMessage(Tips tips_, bytes32 sender_, bytes32 recipient_, Request request_, bytes memory content_)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return abi.encodePacked(tips_, sender_, recipient_, request_, content_);\n    }\n\n    /**\n     * @notice Returns a BaseMessage view over the given payload.\n     * @dev Will revert if the payload is not a base message.\n     */\n    function castToBaseMessage(bytes memory payload) internal pure returns (BaseMessage) {\n        return castToBaseMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a BaseMessage view.\n     * @dev Will revert if the memory view is not over a base message payload.\n     */\n    function castToBaseMessage(MemView memView) internal pure returns (BaseMessage) {\n        if (!isBaseMessage(memView)) revert UnformattedBaseMessage();\n        return BaseMessage.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted BaseMessage.\n    function isBaseMessage(MemView memView) internal pure returns (bool) {\n        // Check if sender, recipient, tips fields exist\n        return (memView.len() \u003e= OFFSET_CONTENT);\n        // Content could be empty, so we don't check that\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(BaseMessage baseMessage) internal pure returns (MemView) {\n        return MemView.wrap(BaseMessage.unwrap(baseMessage));\n    }\n\n    /// @notice Returns baseMessage's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        // We hash \"tips\" and \"everything but tips\" to make tips proofs easier to verify\n        return MerkleMath.getParent(baseMessage.tips().leaf(), baseMessage.bodyLeaf());\n    }\n\n    /// @notice Returns hash for the \"everything but tips\" part of the base message.\n    function bodyLeaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_SENDER}).keccak();\n    }\n\n    // ═══════════════════════════════════════════ BASE MESSAGE SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips paid on origin chain.\n    function tips(BaseMessage baseMessage) internal pure returns (Tips) {\n        return TipsLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_TIPS, bytes_: TIPS_LENGTH})));\n    }\n\n    /// @notice Returns sender address on origin chain.\n    function sender(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_SENDER, bytes_: 32});\n    }\n\n    /// @notice Returns recipient address on destination chain.\n    function recipient(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_RECIPIENT, bytes_: 32});\n    }\n\n    /// @notice Returns an encoded request for message execution on destination chain.\n    function request(BaseMessage baseMessage) internal pure returns (Request) {\n        return RequestLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_REQUEST, bytes_: REQUEST_LENGTH})));\n    }\n\n    /// @notice Returns an untyped memory view over the content to be passed to recipient.\n    function content(BaseMessage baseMessage) internal pure returns (MemView) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_CONTENT});\n    }\n}\n\n// contracts/base/MessagingBase.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for all messaging contracts.\n * - Provides context on the local chain's domain.\n * - Provides ownership functionality.\n * - Will be providing pausing functionality when it is implemented.\n */\nabstract contract MessagingBase is MultiCallable, Versioned, Ownable2StepUpgradeable {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @notice Domain of the local chain, set once upon contract creation\n    uint32 public immutable localDomain;\n    // @notice Domain of the Synapse chain, set once upon contract creation\n    uint32 public immutable synapseDomain;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev gap for upgrade safety\n    uint256[50] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    constructor(string memory version_, uint32 synapseDomain_) Versioned(version_) {\n        localDomain = ChainContext.chainId();\n        synapseDomain = synapseDomain_;\n    }\n\n    // TODO: Implement pausing\n\n    /**\n     * @dev Should be impossible to renounce ownership;\n     * we override OpenZeppelin OwnableUpgradeable's\n     * implementation of renounceOwnership to make it a no-op\n     */\n    function renounceOwnership() public override onlyOwner {} //solhint-disable-line no-empty-blocks\n}\n\n// contracts/libs/memory/Message.sol\n\n/// Message is a memory over over a formatted message payload.\ntype Message is uint256;\n\nusing MessageLib for Message global;\n\n/// Library for formatting the various messages supported by Origin and Destination.\n///\n/// # Message memory layout\n///\n/// | Position   | Field  | Type    | Bytes | Description                                             |\n/// | ---------- | ------ | ------- | ----- | ------------------------------------------------------- |\n/// | [000..017) | header | uint136 | 17    | Encoded general routing information for the message     |\n/// | [017..AAA) | body   | bytes   | ??    | Formatted payload (according to flag) with message body |\nlibrary MessageLib {\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MemViewLib for bytes;\n    using HeaderLib for MemView;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_HEADER = 0;\n    uint256 private constant OFFSET_BODY = OFFSET_HEADER + HEADER_LENGTH;\n\n    // ══════════════════════════════════════════════════ MESSAGE ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns formatted message with provided fields.\n     * @param header_   Encoded general routing information for the message\n     * @param body_     Formatted payload (according to flag) with message body\n     * @return Formatted message\n     */\n    function formatMessage(Header header_, bytes memory body_) internal pure returns (bytes memory) {\n        return abi.encodePacked(header_, body_);\n    }\n\n    /**\n     * @notice Returns a Message view over for the given payload.\n     * @dev Will revert if the payload is not a message payload.\n     */\n    function castToMessage(bytes memory payload) internal pure returns (Message) {\n        return castToMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Message view.\n     * @dev Will revert if the memory view is not over a message payload.\n     */\n    function castToMessage(MemView memView) internal pure returns (Message) {\n        if (!isMessage(memView)) revert UnformattedMessage();\n        return Message.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Message.\n     */\n    function isMessage(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Check if headers exist in the payload\n        if (length \u003c OFFSET_BODY) return false;\n        // Check that Header is valid\n        uint256 paddedHeader = _header(memView);\n        if (!HeaderLib.isHeader(paddedHeader)) return false;\n        // Check that body is formatted according to the flag\n        // Only Base/Manager message flags exist\n        if (HeaderLib.wrapPadded(paddedHeader).flag() == MessageFlag.Base) {\n            // Check if body is a formatted base message\n            return _body(memView).isBaseMessage();\n        } else {\n            // Check if body is a formatted calldata for AgentManager call\n            return _body(memView).isCallData();\n        }\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Message message) internal pure returns (MemView) {\n        return MemView.wrap(Message.unwrap(message));\n    }\n\n    /// @notice Returns message's hash: a leaf to be inserted in the Merkle tree.\n    function leaf(Message message) internal pure returns (bytes32) {\n        // We hash header and body separately to make message proofs easier to verify\n        Header header_ = message.header();\n        // Only Base/Manager message flags exist\n        if (header_.flag() == MessageFlag.Base) {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToBaseMessage().leaf());\n        } else {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToCallData().leaf());\n        }\n    }\n\n    // ══════════════════════════════════════════════ MESSAGE SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns message's encoded header field.\n    function header(Message message) internal pure returns (Header) {\n        return HeaderLib.wrapPadded((message.unwrap().indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH})));\n    }\n\n    /// @notice Returns message's body field as an untyped memory view.\n    function body(Message message) internal pure returns (MemView) {\n        MemView memView = message.unwrap();\n        return _body(memView);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns message's padded header without checking that it is a valid header.\n    function _header(MemView memView) private pure returns (uint256) {\n        return memView.indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH});\n    }\n\n    /// @dev Returns an untyped memory view over the body field without checking\n    /// if the whole payload or the body are properly formatted.\n    function _body(MemView memView) private pure returns (MemView) {\n        return memView.sliceFrom({index_: OFFSET_BODY});\n    }\n}\n\n// contracts/base/AgentSecured.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for messaging contracts that are secured by the agent manager.\n * `AgentSecured` relies on `AgentManager` to provide the following functionality:\n * - Keep track of agents and their statuses.\n * - Pass agent-signed statements that were verified by the agent manager.\n * - These statements are considered valid indefinitely, unless the agent is disputed.\n * - Disputes are opened and resolved by the agent manager.\n * \u003e `AgentSecured` implementation should never use statements signed by agents that are disputed.\n */\nabstract contract AgentSecured is MessagingBase, IAgentSecured {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    address public immutable agentManager;\n\n    /// @inheritdoc IAgentSecured\n    address public immutable inbox;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    // (agent index =\u003e their dispute status: flag, openedAt, resolvedAt)\n    mapping(uint32 =\u003e DisputeStatus) internal _disputes;\n\n    /// @dev gap for upgrade safety\n    uint256[49] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    modifier onlyAgentManager() {\n        if (msg.sender != agentManager) revert CallerNotAgentManager();\n        _;\n    }\n\n    modifier onlyInbox() {\n        if (msg.sender != inbox) revert CallerNotInbox();\n        _;\n    }\n\n    constructor(string memory version_, uint32 synapseDomain_, address agentManager_, address inbox_)\n        MessagingBase(version_, synapseDomain_)\n    {\n        agentManager = agentManager_;\n        inbox = inbox_;\n    }\n\n    // ════════════════════════════════════════════ ONLY AGENT MANAGER ═════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external onlyAgentManager {\n        uint40 openedAt = ChainContext.blockTimestamp();\n        DisputeStatus memory status = DisputeStatus({flag: DisputeFlag.Pending, openedAt: openedAt, resolvedAt: 0});\n        _disputes[guardIndex] = status;\n        _disputes[notaryIndex] = status;\n    }\n\n    /// @inheritdoc IAgentSecured\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external onlyAgentManager {\n        // Update the dispute status of the slashed agent first.\n        uint40 resolvedAt = ChainContext.blockTimestamp();\n        _disputes[slashedIndex].flag = DisputeFlag.Slashed;\n        _disputes[slashedIndex].resolvedAt = resolvedAt;\n        // Mark the rival agent as not disputed, if there was an ongoing dispute.\n        if (rivalIndex != 0) {\n            _disputes[rivalIndex].flag = DisputeFlag.None;\n            _disputes[rivalIndex].resolvedAt = resolvedAt;\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function agentStatus(address agent) external view returns (AgentStatus memory) {\n        return _agentStatus(agent);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status) {\n        return _getAgent(index);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory) {\n        return _disputes[agentIndex];\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns status of the given agent: (flag, domain, index).\n    function _agentStatus(address agent) internal view returns (AgentStatus memory) {\n        return IAgentManager(agentManager).agentStatus(agent);\n    }\n\n    /// @dev Returns agent and their status for a given agent index. Returns zero values for non existing indexes.\n    function _getAgent(uint256 index) internal view returns (address agent, AgentStatus memory status) {\n        return IAgentManager(agentManager).getAgent(index);\n    }\n\n    /// @dev Checks if a Dispute exists for the given Notary. This function returns true, if\n    /// Notary is in ongoing Dispute, or if Dispute was resolved not in Notary's favor.\n    /// In both cases we can't trust Notary's data.\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeExists(uint32 notaryIndex) internal view returns (bool) {\n        return _disputes[notaryIndex].flag != DisputeFlag.None;\n    }\n\n    /// @dev Checks if a Notary recently won a Dispute and is still in the \"post-dispute\" timeout period.\n    /// In this period we still can't trust Notary's data, though we can optimistically assume that\n    /// that the data will be correct after the timeout (assuming no new Disputes are opened).\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeTimeout(uint32 notaryIndex) internal view returns (bool) {\n        DisputeStatus memory status = _disputes[notaryIndex];\n        // Exit early if Notary is in ongoing Dispute / slashed.\n        if (status.flag != DisputeFlag.None) return false;\n        // Check if Notary has been in any Dispute at all.\n        if (status.openedAt == 0) return false;\n        // Otherwise check if the Dispute timeout is still active.\n        return block.timestamp \u003c status.resolvedAt + DISPUTE_TIMEOUT_NOTARY;\n    }\n}\n\n// contracts/hubs/StateHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StateHub` is a parent contract for `Origin`. It is responsible for the following:\n/// - Keeping track of the historical Origin Merkle Tree containing all the message hashes.\n/// - Keeping track of the historical Origin States, as well as verifying their validity.\nabstract contract StateHub is AgentSecured, StateHubEvents, IStateHub {\n    using SafeCast for uint256;\n    using StateLib for bytes;\n\n    struct OriginState {\n        uint40 blockNumber;\n        uint40 timestamp;\n        GasData gasData;\n    }\n    // Bits left for tight packing: 80\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Historical Merkle Tree\n    /// Note: Takes two storage slots\n    HistoricalTree private _tree;\n\n    /// @dev All historical contract States\n    OriginState[] private _originStates;\n\n    /// @dev gap for upgrade safety\n    uint256[47] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IStateHub\n    function isValidState(bytes memory statePayload) external view returns (bool isValid) {\n        // This will revert if payload is not a formatted state\n        State state = statePayload.castToState();\n        return _isValidState(state);\n    }\n\n    /// @inheritdoc IStateHub\n    function statesAmount() external view returns (uint256) {\n        return _originStates.length;\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestLatestState() external view returns (bytes memory stateData) {\n        // This never underflows, assuming the contract was initialized\n        return suggestState(_nextNonce() - 1);\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestState(uint32 nonce) public view returns (bytes memory stateData) {\n        // This will revert if nonce is out of range\n        bytes32 root = _tree.root(nonce);\n        return _formatOriginState(_originStates[nonce], root, localDomain, nonce);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Initializes the saved states list by inserting a state for an empty Merkle Tree.\n    function _initializeStates() internal {\n        // This should only be called once, when the contract is initialized\n        // This will revert if _tree.roots is non-empty\n        bytes32 savedRoot = _tree.initializeRoots();\n        // Save root for empty merkle _tree with block number and timestamp of initialization\n        _saveState(savedRoot, _toOriginState());\n    }\n\n    /// @dev Inserts leaf into the Merkle Tree and saves the updated origin State.\n    function _insertAndSave(bytes32 leaf) internal {\n        bytes32 newRoot = _tree.insert(leaf);\n        _saveState(newRoot, _toOriginState());\n    }\n\n    /// @dev Saves an updated state of the Origin contract\n    function _saveState(bytes32 root, OriginState memory state) internal {\n        uint32 nonce = _nextNonce();\n        _originStates.push(state);\n        // Emit event with raw state data\n        emit StateSaved(_formatOriginState(state, root, localDomain, nonce));\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns nonce of the next sent message: the amount of saved States so far.\n    /// This always equals to \"total amount of sent messages\" plus 1.\n    function _nextNonce() internal view returns (uint32) {\n        // TODO: consider using more than 32 bits for origin nonces\n        return _originStates.length.toUint32();\n    }\n\n    /// @dev Checks if a state is valid, i.e. if it matches the historical one.\n    /// Reverts, if state refers to another Origin contract.\n    function _isValidState(State state) internal view returns (bool) {\n        // Check if state refers to this contract\n        if (state.origin() != localDomain) revert IncorrectOriginDomain();\n        // Check if nonce exists\n        uint32 nonce = state.nonce();\n        if (nonce \u003e= _originStates.length) return false;\n        // Check if state root matches the historical one\n        if (state.root() != _tree.root(nonce)) return false;\n        // Check if state metadata matches the historical one\n        return _areEqual(state, _originStates[nonce]);\n    }\n\n    // ═════════════════════════════════════════════ STRUCT FORMATTING ═════════════════════════════════════════════════\n\n    /// @dev Returns a formatted payload for a stored OriginState.\n    function _formatOriginState(OriginState memory originState, bytes32 root, uint32 origin, uint32 nonce)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return StateLib.formatState({\n            root_: root,\n            origin_: origin,\n            nonce_: nonce,\n            blockNumber_: originState.blockNumber,\n            timestamp_: originState.timestamp,\n            gasData_: originState.gasData\n        });\n    }\n\n    /// @dev Child contract should implement the logic for getting the current gas data from the gas oracle\n    /// to be saved as part of the Origin State.\n    // solhint-disable-next-line ordering\n    function _fetchGasData() internal view virtual returns (GasData);\n\n    /// @dev Returns a OriginState struct to save in the contract.\n    function _toOriginState() internal view returns (OriginState memory originState) {\n        originState.blockNumber = ChainContext.blockNumber();\n        originState.timestamp = ChainContext.blockTimestamp();\n        originState.gasData = _fetchGasData();\n    }\n\n    /// @dev Checks that a state and its Origin representation are equal.\n    function _areEqual(State state, OriginState memory originState) internal pure returns (bool) {\n        return state.blockNumber() == originState.blockNumber \u0026\u0026 state.timestamp() == originState.timestamp;\n    }\n}\n\n// contracts/Origin.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Origin` contract is used for sending messages to remote chains. It is done\n/// by inserting the message hashes into the Origin Merkle, which makes it possible to\n/// prove that message was sent using the Merkle proof against the Origin Merkle Root. This essentially\n/// compresses the list of messages into a single 32-byte value that needs to be stored on the destination chain.\n/// `Origin` is responsible for the following:\n/// - Formatting the sent message payloads, and inserting their hashes into the Origin Merkle Tree.\n/// - Keeping track of its own historical states (see parent contract `StateHub`).\n/// - Enforcing minimum tip values for sent base messages based on the provided execution requests.\n/// - Distributing the collected tips upon request from a local `AgentManager` contract.\ncontract Origin is StateHub, OriginEvents, InterfaceOrigin {\n    using MemViewLib for bytes;\n    using MessageLib for bytes;\n    using TipsLib for bytes;\n    using TypeCasts for address;\n\n    address public immutable gasOracle;\n\n    modifier onlyRemoteDestination(uint32 destination) {\n        if (destination == localDomain) revert IncorrectDestinationDomain();\n        _;\n    }\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_, address gasOracle_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {\n        gasOracle = gasOracle_;\n    }\n\n    /// @notice Initializes Origin contract:\n    /// - msg.sender is set as contract owner\n    /// - State of \"empty merkle tree\" is saved\n    function initialize() external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize \"states\": state of an \"empty merkle tree\" is saved\n        _initializeStates();\n    }\n\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable onlyRemoteDestination(destination) returns (uint32 messageNonce, bytes32 messageHash) {\n        // Check that content is not too large\n        if (content.length \u003e MAX_CONTENT_BYTES) revert ContentLengthTooBig();\n        // This will revert if msg.value is lower than value of minimum tips\n        Tips tips = _getMinimumTips(destination, paddedRequest, content.length).matchValue(msg.value);\n        Request request = RequestLib.wrapPadded(paddedRequest);\n        // Format the BaseMessage body\n        bytes memory body = BaseMessageLib.formatBaseMessage({\n            sender_: msg.sender.addressToBytes32(),\n            recipient_: recipient,\n            tips_: tips,\n            request_: request,\n            content_: content\n        });\n        // Send the message\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Base, body);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        onlyAgentManager\n        onlyRemoteDestination(destination)\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // AgentManager (checked via modifier) is responsible for constructing the calldata payload correctly.\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Manager, payload);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function withdrawTips(address recipient, uint256 amount) external onlyAgentManager {\n        if (address(this).balance \u003c amount) revert InsufficientEthBalance();\n        (bool success,) = recipient.call{value: amount}(\"\");\n        if (!success) revert EthTransferFailed();\n        emit TipWithdrawalCompleted(recipient, amount);\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue)\n    {\n        return _getMinimumTips(destination, paddedRequest, contentLength).value();\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Sends the given message to the specified destination. Message hash is inserted\n    /// into the Origin Merkle Tree, which will enable message execution on destination chain.\n    function _sendMessage(uint32 destination, uint32 optimisticPeriod, MessageFlag flag, bytes memory body)\n        internal\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // Format the message header\n        messageNonce = _nextNonce();\n        Header header = flag.encodeHeader({\n            origin_: localDomain,\n            nonce_: messageNonce,\n            destination_: destination,\n            optimisticPeriod_: optimisticPeriod\n        });\n        // Format the full message payload\n        bytes memory msgPayload = MessageLib.formatMessage(header, body);\n        // Insert new leaf into the Origin Merkle Tree and save the updated state\n        messageHash = msgPayload.castToMessage().leaf();\n        _insertAndSave(messageHash);\n        // Emit event with message information\n        emit Sent(messageHash, messageNonce, destination, msgPayload);\n        // Update the gas oracle data. We do this after the provided tips are checked so that\n        // the provided message is sent in the event that the gas oracle data is updated to a higher value.\n        InterfaceGasOracle(gasOracle).updateGasData(destination);\n        // TODO: consider doing this before the message is sent, while adjusting GasOracle.getMinimumTips() to\n        // use the pending gas oracle data.\n    }\n\n    /// @dev Returns the minimum tips for sending a message to the given destination with the given request and content.\n    function _getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        internal\n        view\n        returns (Tips)\n    {\n        return\n            TipsLib.wrapPadded(InterfaceGasOracle(gasOracle).getMinimumTips(destination, paddedRequest, contentLength));\n    }\n\n    /// @dev Gets the current gas data from the gas oracle to be saved as part of the Origin State.\n    function _fetchGasData() internal view override returns (GasData) {\n        return GasDataLib.wrapGasData(InterfaceGasOracle(gasOracle).getGasData());\n    }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[],"name":"agentRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"agent","type":"address"}],"name":"agentStatus","outputs":[{"components":[{"internalType":"enum AgentFlag","name":"flag","type":"uint8"},{"internalType":"uint32","name":"domain","type":"uint32"},{"internalType":"uint32","name":"index","type":"uint32"}],"internalType":"struct AgentStatus","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"agent","type":"address"}],"name":"disputeStatus","outputs":[{"internalType":"enum DisputeFlag","name":"flag","type":"uint8"},{"internalType":"address","name":"rival","type":"address"},{"internalType":"address","name":"fraudProver","type":"address"},{"internalType":"uint256","name":"disputePtr","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getAgent","outputs":[{"internalType":"address","name":"agent","type":"address"},{"components":[{"internalType":"enum AgentFlag","name":"flag","type":"uint8"},{"internalType":"uint32","name":"domain","type":"uint32"},{"internalType":"uint32","name":"index","type":"uint32"}],"internalType":"struct AgentStatus","name":"status","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getDispute","outputs":[{"internalType":"address","name":"guard","type":"address"},{"internalType":"address","name":"notary","type":"address"},{"internalType":"address","name":"slashedAgent","type":"address"},{"internalType":"address","name":"fraudProver","type":"address"},{"internalType":"bytes","name":"reportPayload","type":"bytes"},{"internalType":"bytes","name":"reportSignature","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDisputesAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"guardIndex","type":"uint32"},{"internalType":"uint32","name":"notaryIndex","type":"uint32"}],"name":"openDispute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"domain","type":"uint32"},{"internalType":"address","name":"agent","type":"address"},{"internalType":"address","name":"prover","type":"address"}],"name":"slashAgent","outputs":[],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{"agentRoot()":{"notice":"Returns the latest known root of the Agent Merkle Tree."},"agentStatus(address)":{"notice":"Returns (flag, domain, index) for a given agent. See Structures.sol for details."},"disputeStatus(address)":{"notice":"Returns the current Dispute status of a given agent. See Structures.sol for details."},"getAgent(uint256)":{"notice":"Returns agent address and their current status for a given agent index."},"getDispute(uint256)":{"notice":"Returns information about the dispute with the given index."},"getDisputesAmount()":{"notice":"Returns the number of opened Disputes."},"openDispute(uint32,uint32)":{"notice":"Allows Inbox to open a Dispute between a Guard and a Notary, if they are both not in Dispute already. \u003e Will revert if any of these is true: \u003e - Caller is not Inbox. \u003e - Guard or Notary is already in Dispute."},"slashAgent(uint32,address,address)":{"notice":"Allows Inbox to slash an agent, if their fraud was proven. \u003e Will revert if any of these is true: \u003e - Caller is not Inbox. \u003e - Domain doesn't match the saved agent domain."}},"version":1},"developerDoc":{"kind":"dev","methods":{"agentStatus(address)":{"details":"Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud, but their status is not updated to Slashed yet.","params":{"agent":"Agent address"},"returns":{"_0":"Status for the given agent: (flag, domain, index)."}},"disputeStatus(address)":{"details":"Every returned value will be set to zero if agent was not slashed and is not in Dispute. `rival` and `disputePtr` will be set to zero if the agent was slashed without being in Dispute.","params":{"agent":"Agent address"},"returns":{"disputePtr":"  Index of the opened Dispute PLUS ONE. Zero if agent is not in Dispute.","flag":"        Flag describing the current Dispute status for the agent: None/Pending/Slashed","fraudProver":" Address who provided fraud proof to resolve the Dispute","rival":"       Address of the rival agent in the Dispute"}},"getAgent(uint256)":{"details":"Will return empty values if agent with given index doesn't exist.","params":{"index":"Agent index in the Agent Merkle Tree"},"returns":{"agent":"   Agent address","status":"  Status for the given agent: (flag, domain, index)"}},"getDispute(uint256)":{"details":"Will revert if dispute with given index hasn't been opened yet.","params":{"index":"Dispute index"},"returns":{"fraudProver":"     Address who provided fraud proof to resolve the Dispute","guard":"           Address of the Guard in the Dispute","notary":"          Address of the Notary in the Dispute","reportPayload":"   Raw payload with report data that led to the Dispute","reportSignature":" Guard signature for the report payload","slashedAgent":"    Address of the Agent who was slashed when Dispute was resolved"}},"getDisputesAmount()":{"details":"This includes the Disputes that have been resolved already."},"openDispute(uint32,uint32)":{"params":{"guardIndex":"Index of the Guard in the Agent Merkle Tree","notaryIndex":"Index of the Notary in the Agent Merkle Tree"}},"slashAgent(uint32,address,address)":{"params":{"agent":"Address of the Agent","domain":"Domain where the Agent is active","prover":"Address that initially provided fraud proof"}}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"agentRoot\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"agent\",\"type\":\"address\"}],\"name\":\"agentStatus\",\"outputs\":[{\"components\":[{\"internalType\":\"enum AgentFlag\",\"name\":\"flag\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"domain\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"index\",\"type\":\"uint32\"}],\"internalType\":\"struct AgentStatus\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"agent\",\"type\":\"address\"}],\"name\":\"disputeStatus\",\"outputs\":[{\"internalType\":\"enum DisputeFlag\",\"name\":\"flag\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"rival\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"fraudProver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"disputePtr\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getAgent\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"agent\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"enum AgentFlag\",\"name\":\"flag\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"domain\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"index\",\"type\":\"uint32\"}],\"internalType\":\"struct AgentStatus\",\"name\":\"status\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getDispute\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"guard\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"notary\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"slashedAgent\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"fraudProver\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"reportPayload\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"reportSignature\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDisputesAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"guardIndex\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"notaryIndex\",\"type\":\"uint32\"}],\"name\":\"openDispute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"domain\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"agent\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"prover\",\"type\":\"address\"}],\"name\":\"slashAgent\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"agentStatus(address)\":{\"details\":\"Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud, but their status is not updated to Slashed yet.\",\"params\":{\"agent\":\"Agent address\"},\"returns\":{\"_0\":\"Status for the given agent: (flag, domain, index).\"}},\"disputeStatus(address)\":{\"details\":\"Every returned value will be set to zero if agent was not slashed and is not in Dispute. `rival` and `disputePtr` will be set to zero if the agent was slashed without being in Dispute.\",\"params\":{\"agent\":\"Agent address\"},\"returns\":{\"disputePtr\":\"  Index of the opened Dispute PLUS ONE. Zero if agent is not in Dispute.\",\"flag\":\"        Flag describing the current Dispute status for the agent: None/Pending/Slashed\",\"fraudProver\":\" Address who provided fraud proof to resolve the Dispute\",\"rival\":\"       Address of the rival agent in the Dispute\"}},\"getAgent(uint256)\":{\"details\":\"Will return empty values if agent with given index doesn't exist.\",\"params\":{\"index\":\"Agent index in the Agent Merkle Tree\"},\"returns\":{\"agent\":\"   Agent address\",\"status\":\"  Status for the given agent: (flag, domain, index)\"}},\"getDispute(uint256)\":{\"details\":\"Will revert if dispute with given index hasn't been opened yet.\",\"params\":{\"index\":\"Dispute index\"},\"returns\":{\"fraudProver\":\"     Address who provided fraud proof to resolve the Dispute\",\"guard\":\"           Address of the Guard in the Dispute\",\"notary\":\"          Address of the Notary in the Dispute\",\"reportPayload\":\"   Raw payload with report data that led to the Dispute\",\"reportSignature\":\" Guard signature for the report payload\",\"slashedAgent\":\"    Address of the Agent who was slashed when Dispute was resolved\"}},\"getDisputesAmount()\":{\"details\":\"This includes the Disputes that have been resolved already.\"},\"openDispute(uint32,uint32)\":{\"params\":{\"guardIndex\":\"Index of the Guard in the Agent Merkle Tree\",\"notaryIndex\":\"Index of the Notary in the Agent Merkle Tree\"}},\"slashAgent(uint32,address,address)\":{\"params\":{\"agent\":\"Address of the Agent\",\"domain\":\"Domain where the Agent is active\",\"prover\":\"Address that initially provided fraud proof\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"agentRoot()\":{\"notice\":\"Returns the latest known root of the Agent Merkle Tree.\"},\"agentStatus(address)\":{\"notice\":\"Returns (flag, domain, index) for a given agent. See Structures.sol for details.\"},\"disputeStatus(address)\":{\"notice\":\"Returns the current Dispute status of a given agent. See Structures.sol for details.\"},\"getAgent(uint256)\":{\"notice\":\"Returns agent address and their current status for a given agent index.\"},\"getDispute(uint256)\":{\"notice\":\"Returns information about the dispute with the given index.\"},\"getDisputesAmount()\":{\"notice\":\"Returns the number of opened Disputes.\"},\"openDispute(uint32,uint32)\":{\"notice\":\"Allows Inbox to open a Dispute between a Guard and a Notary, if they are both not in Dispute already. \u003e Will revert if any of these is true: \u003e - Caller is not Inbox. \u003e - Guard or Notary is already in Dispute.\"},\"slashAgent(uint32,address,address)\":{\"notice\":\"Allows Inbox to slash an agent, if their fraud was proven. \u003e Will revert if any of these is true: \u003e - Caller is not Inbox. \u003e - Domain doesn't match the saved agent domain.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Origin.sol\":\"IAgentManager\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Origin.sol\":{\"keccak256\":\"0x96775924f147f3d1f8df8cdf56731fe52a15af8d8e12e608efb8158c112b18cd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e642a27f5fab3c62b4c02e9754e9e42b1cf2e5381dbea9d3d106d23b7772ebe6\",\"dweb:/ipfs/QmUwn7ZyBvPkjnMuK8ZMSexBUdNQnVtxwyoAyT4DXLQjra\"]}},\"version\":1}"},"hashes":{"agentRoot()":"36cba43c","agentStatus(address)":"28f3fac9","disputeStatus(address)":"3463d1b1","getAgent(uint256)":"2de5aaf7","getDispute(uint256)":"e3a96cbd","getDisputesAmount()":"3aaeccc6","openDispute(uint32,uint32)":"a2155c34","slashAgent(uint32,address,address)":"2853a0e6"}},"solidity/Origin.sol:IAgentSecured":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/OriginEvents.sol\n\n/// @notice A collection of events emitted by the Origin contract\nabstract contract OriginEvents {\n    /**\n     * @notice Emitted when a new message is sent.\n     * @param messageHash   Hash of message; the leaf inserted to the Merkle tree for the message\n     * @param nonce         Nonce of sent message (starts from 1)\n     * @param destination   Destination domain\n     * @param message       Raw bytes of message\n     */\n    event Sent(bytes32 indexed messageHash, uint32 indexed nonce, uint32 indexed destination, bytes message);\n\n    /**\n     * @notice Emitted when a tip withdrawal is completed.\n     * @param actor     Actor address\n     * @param tip       Tip value, denominated in local domain's wei\n     */\n    event TipWithdrawalCompleted(address actor, uint256 tip);\n}\n\n// contracts/events/StateHubEvents.sol\n\n/// @notice A collection of events emitted by the StateHub contract\nabstract contract StateHubEvents {\n    /**\n     * @notice Emitted when a new Origin State is saved after a message was sent.\n     * @param state     Raw payload with state data\n     */\n    event StateSaved(bytes state);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n    /**\n     * @notice Check that a given state is valid: matches the historical state of Origin contract.\n     * Note: any Agent including an invalid state in their snapshot will be slashed\n     * upon providing the snapshot and agent signature for it to Origin contract.\n     * @dev Will revert if any of these is true:\n     *  - State payload is not properly formatted.\n     * @param statePayload      Raw payload with state data\n     * @return isValid          Whether the provided state is valid\n     */\n    function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns the amount of saved states so far.\n     * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n     */\n    function statesAmount() external view returns (uint256);\n\n    /**\n     * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @return statePayload     Raw payload with the latest state data\n     */\n    function suggestLatestState() external view returns (bytes memory statePayload);\n\n    /**\n     * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @param nonce             Historical nonce to form a state\n     * @return statePayload     Raw payload with historical state data\n     */\n    function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/InterfaceGasOracle.sol\n\ninterface InterfaceGasOracle {\n    /**\n     * @notice Fetches the latest gas data for the chain from `Destination` contract,\n     * and uses it to update the oracle values for the requested chain.\n     * @param domain    Domain to update the gas data for\n     */\n    function updateGasData(uint32 domain) external;\n\n    /**\n     * @notice Returns the gas data for the local chain.\n     */\n    function getGasData() external view returns (uint256 paddedGasData);\n\n    /**\n     * @notice Returns the gas data for the given domain, in the decoded format.\n     * @param domain        Domain of chain to get gas data for\n     * @return gasPrice     Gas price for the chain (in Wei per gas unit)\n     * @return dataPrice    Calldata price (in Wei per byte of content)\n     * @return execBuffer   Tx fee safety buffer for message execution (in Wei)\n     * @return amortAttCost Amortized cost for attestation submission (in Wei)\n     * @return etherPrice   Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n     * @return markup       Markup for the message execution (in BWAD)\n     */\n    function getDecodedGasData(uint32 domain)\n        external\n        view\n        returns (\n            uint256 gasPrice,\n            uint256 dataPrice,\n            uint256 execBuffer,\n            uint256 amortAttCost,\n            uint256 etherPrice,\n            uint256 markup\n        );\n\n    /**\n     * @notice Returns the minimum tips for sending a message to a given destination.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return paddedTips       Padded encoded minimum tips information\n     */\n    function getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 paddedTips);\n}\n\n// contracts/interfaces/InterfaceOrigin.sol\n\ninterface InterfaceOrigin {\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /**\n     * @notice Send a message to the recipient located on destination domain.\n     * @dev Recipient has to conform to IMessageRecipient interface, otherwise message won't be delivered.\n     * Will revert if any of these is true:\n     * - `destination` is equal to contract's local domain\n     * - `content` length is greater than `MAX_CONTENT_BYTES`\n     * - `msg.value` is lower than value of minimum tips for the given message\n     * @param destination           Domain of destination chain\n     * @param recipient             Address of recipient on destination chain as bytes32\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param paddedRequest         Padded encoded message execution request on destination chain\n     * @param content               Raw bytes content of message\n     * @return messageNonce         Nonce of the sent message\n     * @return messageHash          Hash of the sent message\n     */\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable returns (uint32 messageNonce, bytes32 messageHash);\n\n    /**\n     * @notice Send a manager message to the destination domain.\n     * @dev This could only be called by AgentManager, which takes care of encoding the calldata payload.\n     * Note: (msgOrigin, proofMaturity) security args will be added to payload on the destination chain\n     * so that the AgentManager could verify where the Manager Message came from and how mature is the proof.\n     * Note: function is not payable, as no tips are required for sending a manager message.\n     * Will revert if `destination` is equal to contract's local domain.\n     * @param destination           Domain of destination chain\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param payload               Payload for calling AgentManager on destination chain (with extra security args)\n     */\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        returns (uint32 messageNonce, bytes32 messageHash);\n\n    // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Withdraws locked base message tips to the recipient.\n     * @dev Could only be called by a local AgentManager.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function withdrawTips(address recipient, uint256 amount) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the minimum tips value for sending a message to a given destination.\n     * @dev Using at least `tipsValue` as `msg.value` for `sendBaseMessage()`\n     * will guarantee that the message will be accepted.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return tipsValue        Minimum tips value for a message to be accepted\n     */\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue);\n}\n\n// contracts/libs/Constants.sol\n\n// Here we define common constants to enable their easier reusing later.\n\n// ══════════════════════════════════ MERKLE ═══════════════════════════════════\n/// @dev Height of the Agent Merkle Tree\nuint256 constant AGENT_TREE_HEIGHT = 32;\n/// @dev Height of the Origin Merkle Tree\nuint256 constant ORIGIN_TREE_HEIGHT = 32;\n/// @dev Height of the Snapshot Merkle Tree. Allows up to 64 leafs, e.g. up to 32 states\nuint256 constant SNAPSHOT_TREE_HEIGHT = 6;\n// ══════════════════════════════════ STRUCTS ══════════════════════════════════\n/// @dev See Attestation.sol: (bytes32,bytes32,uint32,uint40,uint40): 32+32+4+5+5\nuint256 constant ATTESTATION_LENGTH = 78;\n/// @dev See GasData.sol: (uint16,uint16,uint16,uint16,uint16,uint16): 2+2+2+2+2+2\nuint256 constant GAS_DATA_LENGTH = 12;\n/// @dev See Receipt.sol: (uint32,uint32,bytes32,bytes32,uint8,address,address,address): 4+4+32+32+1+20+20+20\nuint256 constant RECEIPT_LENGTH = 133;\n/// @dev See State.sol: (bytes32,uint32,uint32,uint40,uint40,GasData): 32+4+4+5+5+len(GasData)\nuint256 constant STATE_LENGTH = 50 + GAS_DATA_LENGTH;\n/// @dev Maximum amount of states in a single snapshot. Each state produces two leafs in the tree\nuint256 constant SNAPSHOT_MAX_STATES = 1 \u003c\u003c (SNAPSHOT_TREE_HEIGHT - 1);\n// ══════════════════════════════════ MESSAGE ══════════════════════════════════\n/// @dev See Header.sol: (uint8,uint32,uint32,uint32,uint32): 1+4+4+4+4\nuint256 constant HEADER_LENGTH = 17;\n/// @dev See Request.sol: (uint96,uint64,uint32): 12+8+4\nuint256 constant REQUEST_LENGTH = 24;\n/// @dev See Tips.sol: (uint64,uint64,uint64,uint64): 8+8+8+8\nuint256 constant TIPS_LENGTH = 32;\n/// @dev The amount of discarded last bits when encoding tip values\nuint256 constant TIPS_GRANULARITY = 32;\n/// @dev Tip values could be only the multiples of TIPS_MULTIPLIER\nuint256 constant TIPS_MULTIPLIER = 1 \u003c\u003c TIPS_GRANULARITY;\n// ══════════════════════════════ STATEMENT SALTS ══════════════════════════════\n/// @dev Salts for signing various statements\nbytes32 constant ATTESTATION_VALID_SALT = keccak256(\"ATTESTATION_VALID_SALT\");\nbytes32 constant ATTESTATION_INVALID_SALT = keccak256(\"ATTESTATION_INVALID_SALT\");\nbytes32 constant RECEIPT_VALID_SALT = keccak256(\"RECEIPT_VALID_SALT\");\nbytes32 constant RECEIPT_INVALID_SALT = keccak256(\"RECEIPT_INVALID_SALT\");\nbytes32 constant SNAPSHOT_VALID_SALT = keccak256(\"SNAPSHOT_VALID_SALT\");\nbytes32 constant STATE_INVALID_SALT = keccak256(\"STATE_INVALID_SALT\");\n// ═════════════════════════════════ PROTOCOL ══════════════════════════════════\n/// @dev Optimistic period for new agent roots in LightManager\nuint32 constant AGENT_ROOT_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Timeout between the agent root could be proposed and resolved in LightManager\nuint32 constant AGENT_ROOT_PROPOSAL_TIMEOUT = 12 hours;\nuint32 constant BONDING_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Amount of time that the Notary will not be considered active after they won a dispute\nuint32 constant DISPUTE_TIMEOUT_NOTARY = 12 hours;\n/// @dev Amount of time without fresh data from Notaries before contract owner can resolve stuck disputes manually\nuint256 constant FRESH_DATA_TIMEOUT = 4 hours;\n/// @dev Maximum bytes per message = 2 KiB (somewhat arbitrarily set to begin)\nuint256 constant MAX_CONTENT_BYTES = 2 * 2 ** 10;\n/// @dev Maximum value for the summit tip that could be set in GasOracle\nuint256 constant MAX_SUMMIT_TIP = 0.01 ether;\n\n// contracts/libs/Errors.sol\n\n// ══════════════════════════════ INVALID CALLER ═══════════════════════════════\n\nerror CallerNotAgentManager();\nerror CallerNotDestination();\nerror CallerNotInbox();\nerror CallerNotSummit();\n\n// ══════════════════════════════ INCORRECT DATA ═══════════════════════════════\n\nerror IncorrectAttestation();\nerror IncorrectAgentDomain();\nerror IncorrectAgentIndex();\nerror IncorrectAgentProof();\nerror IncorrectAgentRoot();\nerror IncorrectDataHash();\nerror IncorrectDestinationDomain();\nerror IncorrectOriginDomain();\nerror IncorrectSnapshotProof();\nerror IncorrectSnapshotRoot();\nerror IncorrectState();\nerror IncorrectStatesAmount();\nerror IncorrectTipsProof();\nerror IncorrectVersionLength();\n\nerror IncorrectNonce();\nerror IncorrectSender();\nerror IncorrectRecipient();\n\nerror FlagOutOfRange();\nerror IndexOutOfRange();\nerror NonceOutOfRange();\n\nerror OutdatedNonce();\n\nerror UnformattedAttestation();\nerror UnformattedAttestationReport();\nerror UnformattedBaseMessage();\nerror UnformattedCallData();\nerror UnformattedCallDataPrefix();\nerror UnformattedMessage();\nerror UnformattedReceipt();\nerror UnformattedReceiptReport();\nerror UnformattedSignature();\nerror UnformattedSnapshot();\nerror UnformattedState();\nerror UnformattedStateReport();\n\n// ═══════════════════════════════ MERKLE TREES ════════════════════════════════\n\nerror LeafNotProven();\nerror MerkleTreeFull();\nerror NotEnoughLeafs();\nerror TreeHeightTooLow();\n\n// ═════════════════════════════ OPTIMISTIC PERIOD ═════════════════════════════\n\nerror BaseClientOptimisticPeriod();\nerror MessageOptimisticPeriod();\nerror SlashAgentOptimisticPeriod();\nerror WithdrawTipsOptimisticPeriod();\nerror ZeroProofMaturity();\n\n// ═══════════════════════════════ AGENT MANAGER ═══════════════════════════════\n\nerror AgentNotGuard();\nerror AgentNotNotary();\n\nerror AgentCantBeAdded();\nerror AgentNotActive();\nerror AgentNotActiveNorUnstaking();\nerror AgentNotFraudulent();\nerror AgentNotUnstaking();\nerror AgentUnknown();\n\nerror AgentRootNotProposed();\nerror AgentRootTimeoutNotOver();\n\nerror NotStuck();\n\nerror DisputeAlreadyResolved();\nerror DisputeNotOpened();\nerror DisputeTimeoutNotOver();\nerror GuardInDispute();\nerror NotaryInDispute();\n\nerror MustBeSynapseDomain();\nerror SynapseDomainForbidden();\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\nerror AlreadyExecuted();\nerror AlreadyFailed();\nerror DuplicatedSnapshotRoot();\nerror IncorrectMagicValue();\nerror GasLimitTooLow();\nerror GasSuppliedTooLow();\n\n// ══════════════════════════════════ ORIGIN ═══════════════════════════════════\n\nerror ContentLengthTooBig();\nerror EthTransferFailed();\nerror InsufficientEthBalance();\n\n// ════════════════════════════════ GAS ORACLE ═════════════════════════════════\n\nerror LocalGasDataNotSet();\nerror RemoteGasDataNotSet();\n\n// ═══════════════════════════════════ TIPS ════════════════════════════════════\n\nerror SummitTipTooHigh();\nerror TipsClaimMoreThanEarned();\nerror TipsClaimZero();\nerror TipsOverflow();\nerror TipsValueTooLow();\n\n// ════════════════════════════════ MEMORY VIEW ════════════════════════════════\n\nerror IndexedTooMuch();\nerror ViewOverrun();\nerror OccupiedMemory();\nerror UnallocatedMemory();\nerror PrecompileOutOfGas();\n\n// ═════════════════════════════════ MULTICALL ═════════════════════════════════\n\nerror MulticallFailed();\n\n// contracts/libs/TypeCasts.sol\n\nlibrary TypeCasts {\n    // alignment preserving cast\n    function addressToBytes32(address addr) internal pure returns (bytes32) {\n        return bytes32(uint256(uint160(addr)));\n    }\n\n    // alignment preserving cast\n    function bytes32ToAddress(bytes32 buf) internal pure returns (address) {\n        return address(uint160(uint256(buf)));\n    }\n}\n\n// contracts/libs/stack/Number.sol\n\n/// Number is a compact representation of uint256, that is fit into 16 bits\n/// with the maximum relative error under 0.4%.\ntype Number is uint16;\n\nusing NumberLib for Number global;\n\n/// # Number\n/// Library for compact representation of uint256 numbers.\n/// - Number is stored using mantissa and exponent, each occupying 8 bits.\n/// - Numbers under 2**8 are stored as `mantissa` with `exponent = 0xFF`.\n/// - Numbers at least 2**8 are approximated as `(256 + mantissa) \u003c\u003c exponent`\n/// \u003e - `0 \u003c= mantissa \u003c 256`\n/// \u003e - `0 \u003c= exponent \u003c= 247` (`256 * 2**248` doesn't fit into uint256)\n/// # Number stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type  | Bytes |\n/// | ---------- | -------- | ----- | ----- |\n/// | (002..001] | mantissa | uint8 | 1     |\n/// | (001..000] | exponent | uint8 | 1     |\n\nlibrary NumberLib {\n    /// @dev Amount of bits to shift to mantissa field\n    uint16 private constant SHIFT_MANTISSA = 8;\n\n    /// @notice For bwad math (binary wad) we use 2**64 as \"wad\" unit.\n    /// @dev We are using not using 10**18 as wad, because it is not stored precisely in NumberLib.\n    uint256 internal constant BWAD_SHIFT = 64;\n    uint256 internal constant BWAD = 1 \u003c\u003c BWAD_SHIFT;\n    /// @notice ~0.1% in bwad units.\n    uint256 internal constant PER_MILLE_SHIFT = BWAD_SHIFT - 10;\n    uint256 internal constant PER_MILLE = 1 \u003c\u003c PER_MILLE_SHIFT;\n\n    /// @notice Compresses uint256 number into 16 bits.\n    function compress(uint256 value) internal pure returns (Number) {\n        // Find `msb` such as `2**msb \u003c= value \u003c 2**(msb + 1)`\n        uint256 msb = mostSignificantBit(value);\n        // We want to preserve 9 bits of precision.\n        // The highest bit is always 1, so we can skip it.\n        // The remaining 8 highest bits are stored as mantissa.\n        if (msb \u003c 8) {\n            // Value is less than 2**8, so we can use value as mantissa with \"-1\" exponent.\n            return _encode(uint8(value), 0xFF);\n        } else {\n            // We use `msb - 8` as exponent otherwise. Note that `exponent \u003e= 0`.\n            unchecked {\n                uint256 exponent = msb - 8;\n                // Shifting right by `msb-8` bits will shift the \"remaining 8 highest bits\" into the 8 lowest bits.\n                // uint8() will truncate the highest bit.\n                return _encode(uint8(value \u003e\u003e exponent), uint8(exponent));\n            }\n        }\n    }\n\n    /// @notice Decompresses 16 bits number into uint256.\n    /// @dev The outcome is an approximation of the original number: `(value - value / 256) \u003c number \u003c= value`.\n    function decompress(Number number) internal pure returns (uint256 value) {\n        // Isolate 8 highest bits as the mantissa.\n        uint256 mantissa = Number.unwrap(number) \u003e\u003e SHIFT_MANTISSA;\n        // This will truncate the highest bits, leaving only the exponent.\n        uint256 exponent = uint8(Number.unwrap(number));\n        if (exponent == 0xFF) {\n            return mantissa;\n        } else {\n            unchecked {\n                return (256 + mantissa) \u003c\u003c (exponent);\n            }\n        }\n    }\n\n    /// @dev Returns the most significant bit of `x`\n    /// https://solidity-by-example.org/bitwise/\n    function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\n        // To find `msb` we determine it bit by bit, starting from the highest one.\n        // `0 \u003c= msb \u003c= 255`, so we start from the highest bit, 1\u003c\u003c7 == 128.\n        // If `x` is at least 2**128, then the highest bit of `x` is at least 128.\n        // solhint-disable no-inline-assembly\n        assembly {\n            // `f` is set to 1\u003c\u003c7 if `x \u003e= 2**128` and to 0 otherwise.\n            let f := shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\n            // If `x \u003e= 2**128` then set `msb` highest bit to 1 and shift `x` right by 128.\n            // Otherwise, `msb` remains 0 and `x` remains unchanged.\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        // `x` is now at most 2**128 - 1. Continue the same way, the next highest bit is 1\u003c\u003c6 == 64.\n        assembly {\n            // `f` is set to 1\u003c\u003c6 if `x \u003e= 2**64` and to 0 otherwise.\n            let f := shl(6, gt(x, 0xFFFFFFFFFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c5 if `x \u003e= 2**32` and to 0 otherwise.\n            let f := shl(5, gt(x, 0xFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c4 if `x \u003e= 2**16` and to 0 otherwise.\n            let f := shl(4, gt(x, 0xFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c3 if `x \u003e= 2**8` and to 0 otherwise.\n            let f := shl(3, gt(x, 0xFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c2 if `x \u003e= 2**4` and to 0 otherwise.\n            let f := shl(2, gt(x, 0xF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c1 if `x \u003e= 2**2` and to 0 otherwise.\n            let f := shl(1, gt(x, 0x3))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1 if `x \u003e= 2**1` and to 0 otherwise.\n            let f := gt(x, 0x1)\n            msb := or(msb, f)\n        }\n    }\n\n    /// @dev Wraps (mantissa, exponent) pair into Number.\n    function _encode(uint8 mantissa, uint8 exponent) private pure returns (Number) {\n        // Casts below are upcasts, so they are safe.\n        return Number.wrap(uint16(mantissa) \u003c\u003c SHIFT_MANTISSA | uint16(exponent));\n    }\n}\n\n// contracts/libs/stack/Request.sol\n\n/// Request is encoded data with \"message execution request\".\ntype Request is uint192;\n\nusing RequestLib for Request global;\n\n/// Library for formatting _the request part_ of _the base messages_.\n/// - Request represents a message sender requirements for the message execution on the destination chain.\n/// - Request occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n/// \u003e gasDrop field is included for future compatibility and is ignored at the moment.\n///\n/// # Request stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type   | Bytes | Description                                          |\n/// | ---------- | -------- | ------ | ----- | ---------------------------------------------------- |\n/// | (024..012] | gasDrop  | uint96 | 12    | Minimum amount of gas token to drop to the recipient |\n/// | (012..004] | gasLimit | uint64 | 8     | Minimum amount of gas units to supply for execution  |\n/// | (004..000] | version  | uint32 | 4     | Base message version to pass to the recipient        |\n\nlibrary RequestLib {\n    /// @dev Amount of bits to shift to gasDrop field\n    uint192 private constant SHIFT_GAS_DROP = 12 * 8;\n    /// @dev Amount of bits to shift to gasLimit field\n    uint192 private constant SHIFT_GAS_LIMIT = 4 * 8;\n\n    /// @notice Returns an encoded request with the given fields\n    /// @param gasDrop_     Minimum amount of gas token to drop to the recipient (ignored at the moment)\n    /// @param gasLimit_    Minimum amount of gas units to supply for execution\n    /// @param version_     Base message version to pass to the recipient\n    function encodeRequest(uint96 gasDrop_, uint64 gasLimit_, uint32 version_) internal pure returns (Request) {\n        // Casts below are upcasts, so they are safe\n        return Request.wrap(uint192(gasDrop_) \u003c\u003c SHIFT_GAS_DROP | uint192(gasLimit_) \u003c\u003c SHIFT_GAS_LIMIT | version_);\n    }\n\n    /// @notice Wraps the padded encoded request into a Request-typed value.\n    /// @dev The \"padded\" request is simply an encoded request casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded requests\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedRequest) internal pure returns (Request) {\n        // Casting to uint192 will truncate the highest bits, which is the behavior we want\n        return Request.wrap(uint192(paddedRequest));\n    }\n\n    /// @notice Returns the requested of gas token to drop to the recipient.\n    function gasDrop(Request request) internal pure returns (uint96) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return uint96(Request.unwrap(request) \u003e\u003e SHIFT_GAS_DROP);\n    }\n\n    /// @notice Returns the requested minimum amount of gas units to supply for execution.\n    function gasLimit(Request request) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Request.unwrap(request) \u003e\u003e SHIFT_GAS_LIMIT);\n    }\n\n    /// @notice Returns the requested base message version to pass to the recipient.\n    function version(Request request) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Request.unwrap(request));\n    }\n}\n\n// node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        require(value \u003c= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        require(value \u003c= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        require(value \u003c= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value \u003c= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        require(value \u003c= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        require(value \u003c= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        require(value \u003c= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        require(value \u003c= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        require(value \u003c= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        require(value \u003c= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        require(value \u003c= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        require(value \u003c= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        require(value \u003c= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        require(value \u003c= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        require(value \u003c= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value \u003c= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        require(value \u003c= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        require(value \u003c= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        require(value \u003c= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value \u003c= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        require(value \u003c= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        require(value \u003c= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        require(value \u003c= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value \u003c= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        require(value \u003c= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        require(value \u003c= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        require(value \u003c= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value \u003c= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        require(value \u003c= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value \u003c= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value \u003c= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     *\n     * _Available since v3.0._\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value \u003e= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     *\n     * _Available since v3.0._\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value \u003c= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     *\n     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length \u003e 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance \u003e= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance \u003e= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length \u003e 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n\n// contracts/base/MultiCallable.sol\n\n/// @notice Collection of Multicall utilities. Fork of Multicall3:\n/// https://github.com/mds1/multicall/blob/master/src/Multicall3.sol\nabstract contract MultiCallable {\n    struct Call {\n        bool allowFailure;\n        bytes callData;\n    }\n\n    struct Result {\n        bool success;\n        bytes returnData;\n    }\n\n    /// @notice Aggregates a few calls to this contract into one multicall without modifying `msg.sender`.\n    function multicall(Call[] calldata calls) external returns (Result[] memory callResults) {\n        uint256 amount = calls.length;\n        callResults = new Result[](amount);\n        Call calldata call_;\n        for (uint256 i = 0; i \u003c amount;) {\n            call_ = calls[i];\n            Result memory result = callResults[i];\n            // We perform a delegate call to ourselves here. Delegate call does not modify `msg.sender`, so\n            // this will have the same effect as if `msg.sender` performed all the calls themselves one by one.\n            // solhint-disable-next-line avoid-low-level-calls\n            (result.success, result.returnData) = address(this).delegatecall(call_.callData);\n            // solhint-disable-next-line no-inline-assembly\n            assembly {\n                // Revert if the call fails and failure is not allowed\n                // `allowFailure := calldataload(call_)` and `success := mload(result)`\n                if iszero(or(calldataload(call_), mload(result))) {\n                    // Revert with `0x4d6a2328` (function selector for `MulticallFailed()`)\n                    mstore(0x00, 0x4d6a232800000000000000000000000000000000000000000000000000000000)\n                    revert(0x00, 0x04)\n                }\n            }\n            unchecked {\n                ++i;\n            }\n        }\n    }\n}\n\n// contracts/base/Version.sol\n\n/**\n * @title Versioned\n * @notice Version getter for contracts. Doesn't use any storage slots, meaning\n * it will never cause any troubles with the upgradeable contracts. For instance, this contract\n * can be added or removed from the inheritance chain without shifting the storage layout.\n */\nabstract contract Versioned {\n    /**\n     * @notice Struct that is mimicking the storage layout of a string with 32 bytes or less.\n     * Length is limited by 32, so the whole string payload takes two memory words:\n     * @param length    String length\n     * @param data      String characters\n     */\n    struct _ShortString {\n        uint256 length;\n        bytes32 data;\n    }\n\n    /// @dev Length of the \"version string\"\n    uint256 private immutable _length;\n    /// @dev Bytes representation of the \"version string\".\n    /// Strings with length over 32 are not supported!\n    bytes32 private immutable _data;\n\n    constructor(string memory version_) {\n        _length = bytes(version_).length;\n        if (_length \u003e 32) revert IncorrectVersionLength();\n        // bytes32 is left-aligned =\u003e this will store the byte representation of the string\n        // with the trailing zeroes to complete the 32-byte word\n        _data = bytes32(bytes(version_));\n    }\n\n    function version() external view returns (string memory versionString) {\n        // Load the immutable values to form the version string\n        _ShortString memory str = _ShortString(_length, _data);\n        // The only way to do this cast is doing some dirty assembly\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            versionString := str\n        }\n    }\n}\n\n// contracts/libs/ChainContext.sol\n\n/// @notice Library for accessing chain context variables as tightly packed integers.\n/// Messaging contracts should rely on this library for accessing chain context variables\n/// instead of doing the casting themselves.\nlibrary ChainContext {\n    using SafeCast for uint256;\n\n    /// @notice Returns the current block number as uint40.\n    /// @dev Reverts if block number is greater than 40 bits, which is not supposed to happen\n    /// until the block.timestamp overflows (assuming block time is at least 1 second).\n    function blockNumber() internal view returns (uint40) {\n        return block.number.toUint40();\n    }\n\n    /// @notice Returns the current block timestamp as uint40.\n    /// @dev Reverts if block timestamp is greater than 40 bits, which is\n    /// supposed to happen approximately in year 36835.\n    function blockTimestamp() internal view returns (uint40) {\n        return block.timestamp.toUint40();\n    }\n\n    /// @notice Returns the chain id as uint32.\n    /// @dev Reverts if chain id is greater than 32 bits, which is not\n    /// supposed to happen in production.\n    function chainId() internal view returns (uint32) {\n        return block.chainid.toUint32();\n    }\n}\n\n// contracts/libs/Structures.sol\n\n// Here we define common enums and structures to enable their easier reusing later.\n\n// ═══════════════════════════════ AGENT STATUS ════════════════════════════════\n\n/// @dev Potential statuses for the off-chain bonded agent:\n/// - Unknown: never provided a bond =\u003e signature not valid\n/// - Active: has a bond in BondingManager =\u003e signature valid\n/// - Unstaking: has a bond in BondingManager, initiated the unstaking =\u003e signature not valid\n/// - Resting: used to have a bond in BondingManager, successfully unstaked =\u003e signature not valid\n/// - Fraudulent: proven to commit fraud, value in Merkle Tree not updated =\u003e signature not valid\n/// - Slashed: proven to commit fraud, value in Merkle Tree was updated =\u003e signature not valid\n/// Unstaked agent could later be added back to THE SAME domain by staking a bond again.\n/// Honest agent: Unknown -\u003e Active -\u003e unstaking -\u003e Resting -\u003e Active ...\n/// Malicious agent: Unknown -\u003e Active -\u003e Fraudulent -\u003e Slashed\n/// Malicious agent: Unknown -\u003e Active -\u003e Unstaking -\u003e Fraudulent -\u003e Slashed\nenum AgentFlag {\n    Unknown,\n    Active,\n    Unstaking,\n    Resting,\n    Fraudulent,\n    Slashed\n}\n\n/// @notice Struct for storing an agent in the BondingManager contract.\nstruct AgentStatus {\n    AgentFlag flag;\n    uint32 domain;\n    uint32 index;\n}\n// 184 bits available for tight packing\n\nusing StructureUtils for AgentStatus global;\n\n/// @notice Potential statuses of an agent in terms of being in dispute\n/// - None: agent is not in dispute\n/// - Pending: agent is in unresolved dispute\n/// - Slashed: agent was in dispute that lead to agent being slashed\n/// Note: agent who won the dispute has their status reset to None\nenum DisputeFlag {\n    None,\n    Pending,\n    Slashed\n}\n\n/// @notice Struct for storing dispute status of an agent.\n/// @param flag         Dispute flag: None/Pending/Slashed.\n/// @param openedAt     Timestamp when the latest agent dispute was opened (zero if not opened).\n/// @param resolvedAt   Timestamp when the latest agent dispute was resolved (zero if not resolved).\nstruct DisputeStatus {\n    DisputeFlag flag;\n    uint40 openedAt;\n    uint40 resolvedAt;\n}\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\n/// @notice Struct representing the status of Destination contract.\n/// @param snapRootTime     Timestamp when latest snapshot root was accepted\n/// @param agentRootTime    Timestamp when latest agent root was accepted\n/// @param notaryIndex      Index of Notary who signed the latest agent root\nstruct DestinationStatus {\n    uint40 snapRootTime;\n    uint40 agentRootTime;\n    uint32 notaryIndex;\n}\n\n// ═══════════════════════════════ EXECUTION HUB ═══════════════════════════════\n\n/// @notice Potential statuses of the message in Execution Hub.\n/// - None: there hasn't been a valid attempt to execute the message yet\n/// - Failed: there was a valid attempt to execute the message, but recipient reverted\n/// - Success: there was a valid attempt to execute the message, and recipient did not revert\n/// Note: message can be executed until its status is Success\nenum MessageStatus {\n    None,\n    Failed,\n    Success\n}\n\nlibrary StructureUtils {\n    /// @notice Checks that Agent is Active\n    function verifyActive(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active) {\n            revert AgentNotActive();\n        }\n    }\n\n    /// @notice Checks that Agent is Unstaking\n    function verifyUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Unstaking) {\n            revert AgentNotUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Active or Unstaking\n    function verifyActiveUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active \u0026\u0026 status.flag != AgentFlag.Unstaking) {\n            revert AgentNotActiveNorUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Fraudulent\n    function verifyFraudulent(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Fraudulent) {\n            revert AgentNotFraudulent();\n        }\n    }\n\n    /// @notice Checks that Agent is not Unknown\n    function verifyKnown(AgentStatus memory status) internal pure {\n        if (status.flag == AgentFlag.Unknown) {\n            revert AgentUnknown();\n        }\n    }\n}\n\n// contracts/libs/memory/MemView.sol\n\n/// @dev MemView is an untyped view over a portion of memory to be used instead of `bytes memory`\ntype MemView is uint256;\n\n/// @dev Attach library functions to MemView\nusing MemViewLib for MemView global;\n\n/// @notice Library for operations with the memory views.\n/// Forked from https://github.com/summa-tx/memview-sol with several breaking changes:\n/// - The codebase is ported to Solidity 0.8\n/// - Custom errors are added\n/// - The runtime type checking is replaced with compile-time check provided by User-Defined Value Types\n///   https://docs.soliditylang.org/en/latest/types.html#user-defined-value-types\n/// - uint256 is used as the underlying type for the \"memory view\" instead of bytes29.\n///   It is wrapped into MemView custom type in order not to be confused with actual integers.\n/// - Therefore the \"type\" field is discarded, allowing to allocate 16 bytes for both view location and length\n/// - The documentation is expanded\n/// - Library functions unused by the rest of the codebase are removed\n//  - Very pretty code separators are added :)\nlibrary MemViewLib {\n    /// @notice Stack layout for uint256 (from highest bits to lowest)\n    /// (32 .. 16]      loc     16 bytes    Memory address of underlying bytes\n    /// (16 .. 00]      len     16 bytes    Length of underlying bytes\n\n    // ═══════════════════════════════════════════ BUILDING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Instantiate a new untyped memory view. This should generally not be called directly.\n     * Prefer `ref` wherever possible.\n     * @param loc_          The memory address\n     * @param len_          The length\n     * @return The new view with the specified location and length\n     */\n    function build(uint256 loc_, uint256 len_) internal pure returns (MemView) {\n        uint256 end_ = loc_ + len_;\n        // Make sure that a view is not constructed that points to unallocated memory\n        // as this could be indicative of a buffer overflow attack\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            if gt(end_, mload(0x40)) { end_ := 0 }\n        }\n        if (end_ == 0) {\n            revert UnallocatedMemory();\n        }\n        return _unsafeBuildUnchecked(loc_, len_);\n    }\n\n    /**\n     * @notice Instantiate a memory view from a byte array.\n     * @dev Note that due to Solidity memory representation, it is not possible to\n     * implement a deref, as the `bytes` type stores its len in memory.\n     * @param arr           The byte array\n     * @return The memory view over the provided byte array\n     */\n    function ref(bytes memory arr) internal pure returns (MemView) {\n        uint256 len_ = arr.length;\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 loc_;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // We add 0x20, so that the view starts exactly where the array data starts\n            loc_ := add(arr, 0x20)\n        }\n        return build(loc_, len_);\n    }\n\n    // ════════════════════════════════════════════ CLONING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to the new memory.\n     * @param memView       The memory view\n     * @return arr          The cloned byte array\n     */\n    function clone(MemView memView) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        unchecked {\n            _unsafeCopyTo(memView, ptr + 0x20);\n        }\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 len_ = memView.len();\n        uint256 footprint_ = memView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    /**\n     * @notice Copies all views, joins them into a new bytearray.\n     * @param memViews      The memory views\n     * @return arr          The new byte array with joined data behind the given views\n     */\n    function join(MemView[] memory memViews) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        MemView newView;\n        unchecked {\n            newView = _unsafeJoin(memViews, ptr + 0x20);\n        }\n        uint256 len_ = newView.len();\n        uint256 footprint_ = newView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    // ══════════════════════════════════════════ INSPECTING MEMORY VIEW ═══════════════════════════════════════════════\n\n    /**\n     * @notice Returns the memory address of the underlying bytes.\n     * @param memView       The memory view\n     * @return loc_         The memory address\n     */\n    function loc(MemView memView) internal pure returns (uint256 loc_) {\n        // loc is stored in the highest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u003e\u003e 128;\n    }\n\n    /**\n     * @notice Returns the number of bytes of the view.\n     * @param memView       The memory view\n     * @return len_         The length of the view\n     */\n    function len(MemView memView) internal pure returns (uint256 len_) {\n        // len is stored in the lowest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u0026 type(uint128).max;\n    }\n\n    /**\n     * @notice Returns the endpoint of `memView`.\n     * @param memView       The memory view\n     * @return end_         The endpoint of `memView`\n     */\n    function end(MemView memView) internal pure returns (uint256 end_) {\n        // The endpoint never overflows uint128, let alone uint256, so we could use unchecked math here\n        unchecked {\n            return memView.loc() + memView.len();\n        }\n    }\n\n    /**\n     * @notice Returns the number of memory words this memory view occupies, rounded up.\n     * @param memView       The memory view\n     * @return words_       The number of memory words\n     */\n    function words(MemView memView) internal pure returns (uint256 words_) {\n        // returning ceil(length / 32.0)\n        unchecked {\n            return (memView.len() + 31) \u003e\u003e 5;\n        }\n    }\n\n    /**\n     * @notice Returns the in-memory footprint of a fresh copy of the view.\n     * @param memView       The memory view\n     * @return footprint_   The in-memory footprint of a fresh copy of the view.\n     */\n    function footprint(MemView memView) internal pure returns (uint256 footprint_) {\n        // words() * 32\n        return memView.words() \u003c\u003c 5;\n    }\n\n    // ════════════════════════════════════════════ HASHING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the keccak256 hash of the underlying memory\n     * @param memView       The memory view\n     * @return digest       The keccak256 hash of the underlying memory\n     */\n    function keccak(MemView memView) internal pure returns (bytes32 digest) {\n        uint256 loc_ = memView.loc();\n        uint256 len_ = memView.len();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            digest := keccak256(loc_, len_)\n        }\n    }\n\n    /**\n     * @notice Adds a salt to the keccak256 hash of the underlying data and returns the keccak256 hash of the\n     * resulting data.\n     * @param memView       The memory view\n     * @return digestSalted keccak256(salt, keccak256(memView))\n     */\n    function keccakSalted(MemView memView, bytes32 salt) internal pure returns (bytes32 digestSalted) {\n        return keccak256(bytes.concat(salt, memView.keccak()));\n    }\n\n    // ════════════════════════════════════════════ SLICING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Safe slicing without memory modification.\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the given index\n     */\n    function slice(MemView memView, uint256 index_, uint256 len_) internal pure returns (MemView) {\n        uint256 loc_ = memView.loc();\n        // Ensure it doesn't overrun the view\n        if (loc_ + index_ + len_ \u003e memView.end()) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // loc_ + index_ \u003c= memView.end()\n            return build({loc_: loc_ + index_, len_: len_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing bytes from `index` to end(memView).\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @return The new view for the slice starting from the given index until the initial view endpoint\n     */\n    function sliceFrom(MemView memView, uint256 index_) internal pure returns (MemView) {\n        uint256 len_ = memView.len();\n        // Ensure it doesn't overrun the view\n        if (index_ \u003e len_) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // index_ \u003c= len_ =\u003e memView.loc() + index_ \u003c= memView.loc() + memView.len() == memView.end()\n            return build({loc_: memView.loc() + index_, len_: len_ - index_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the first `len` bytes.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the initial view beginning\n     */\n    function prefix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        return memView.slice({index_: 0, len_: len_});\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the last `len` byte.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length until the initial view endpoint\n     */\n    function postfix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        uint256 viewLen = memView.len();\n        // Ensure it doesn't overrun the view\n        if (len_ \u003e viewLen) {\n            revert ViewOverrun();\n        }\n        // Could do the unchecked math due to the check above\n        uint256 index_;\n        unchecked {\n            index_ = viewLen - len_;\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // len_ \u003c= memView.len() =\u003e memView.loc() \u003c= loc_ \u003c= memView.end()\n            return build({loc_: memView.loc() + viewLen - len_, len_: len_});\n        }\n    }\n\n    // ═══════════════════════════════════════════ INDEXING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Load up to 32 bytes from the view onto the stack.\n     * @dev Returns a bytes32 with only the `bytes_` HIGHEST bytes set.\n     * This can be immediately cast to a smaller fixed-length byte array.\n     * To automatically cast to an integer, use `indexUint`.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return result       The 32 byte result having only `bytes_` highest bytes set\n     */\n    function index(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (bytes32 result) {\n        if (bytes_ == 0) {\n            return bytes32(0);\n        }\n        // Can't load more than 32 bytes to the stack in one go\n        if (bytes_ \u003e 32) {\n            revert IndexedTooMuch();\n        }\n        // The last indexed byte should be within view boundaries\n        if (index_ + bytes_ \u003e memView.len()) {\n            revert ViewOverrun();\n        }\n        uint256 bitLength = bytes_ \u003c\u003c 3; // bytes_ * 8\n        uint256 loc_ = memView.loc();\n        // Get a mask with `bitLength` highest bits set\n        uint256 mask;\n        // 0x800...00 binary representation is 100...00\n        // sar stands for \"signed arithmetic shift\": https://en.wikipedia.org/wiki/Arithmetic_shift\n        // sar(N-1, 100...00) = 11...100..00, with exactly N highest bits set to 1\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            mask := sar(sub(bitLength, 1), 0x8000000000000000000000000000000000000000000000000000000000000000)\n        }\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load a full word using index offset, and apply mask to ignore non-relevant bytes\n            result := and(mload(add(loc_, index_)), mask)\n        }\n    }\n\n    /**\n     * @notice Parse an unsigned integer from the view at `index`.\n     * @dev Requires that the view have \u003e= `bytes_` bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return The unsigned integer\n     */\n    function indexUint(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (uint256) {\n        bytes32 indexedBytes = memView.index(index_, bytes_);\n        // `index()` returns left-aligned `bytes_`, while integers are right-aligned\n        // Shifting here to right-align with the full 32 bytes word: need to shift right `(32 - bytes_)` bytes\n        unchecked {\n            // memView.index() reverts when bytes_ \u003e 32, thus unchecked math\n            return uint256(indexedBytes) \u003e\u003e ((32 - bytes_) \u003c\u003c 3);\n        }\n    }\n\n    /**\n     * @notice Parse an address from the view at `index`.\n     * @dev Requires that the view have \u003e= 20 bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @return The address\n     */\n    function indexAddress(MemView memView, uint256 index_) internal pure returns (address) {\n        // index 20 bytes as `uint160`, and then cast to `address`\n        return address(uint160(memView.indexUint(index_, 20)));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns a memory view over the specified memory location\n    /// without checking if it points to unallocated memory.\n    function _unsafeBuildUnchecked(uint256 loc_, uint256 len_) private pure returns (MemView) {\n        // There is no scenario where loc or len would overflow uint128, so we omit this check.\n        // We use the highest 128 bits to encode the location and the lowest 128 bits to encode the length.\n        return MemView.wrap((loc_ \u003c\u003c 128) | len_);\n    }\n\n    /**\n     * @notice Copy the view to a location, return an unsafe memory reference\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memView       The memory view\n     * @param newLoc        The new location to copy the underlying view data\n     * @return The memory view over the unsafe memory with the copied underlying data\n     */\n    function _unsafeCopyTo(MemView memView, uint256 newLoc) private view returns (MemView) {\n        uint256 len_ = memView.len();\n        uint256 oldLoc = memView.loc();\n\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (newLoc \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        bool res;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // use the identity precompile (0x04) to copy\n            res := staticcall(gas(), 0x04, oldLoc, len_, newLoc, len_)\n        }\n        if (!res) revert PrecompileOutOfGas();\n        return _unsafeBuildUnchecked({loc_: newLoc, len_: len_});\n    }\n\n    /**\n     * @notice Join the views in memory, return an unsafe reference to the memory.\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memViews      The memory views\n     * @return The conjoined view pointing to the new memory\n     */\n    function _unsafeJoin(MemView[] memory memViews, uint256 location) private view returns (MemView) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (location \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        // Copy the views to the specified location one by one, by tracking the amount of copied bytes so far\n        uint256 offset = 0;\n        for (uint256 i = 0; i \u003c memViews.length;) {\n            MemView memView = memViews[i];\n            // We can use the unchecked math here as location + sum(view.length) will never overflow uint256\n            unchecked {\n                _unsafeCopyTo(memView, location + offset);\n                offset += memView.len();\n                ++i;\n            }\n        }\n        return _unsafeBuildUnchecked({loc_: location, len_: offset});\n    }\n}\n\n// contracts/libs/merkle/MerkleMath.sol\n\nlibrary MerkleMath {\n    // ═════════════════════════════════════════ BASIC MERKLE CALCULATIONS ═════════════════════════════════════════════\n\n    /**\n     * @notice Calculates the merkle root for the given leaf and merkle proof.\n     * @dev Will revert if proof length exceeds the tree height.\n     * @param index     Index of `leaf` in tree\n     * @param leaf      Leaf of the merkle tree\n     * @param proof     Proof of inclusion of `leaf` in the tree\n     * @param height    Height of the merkle tree\n     * @return root_    Calculated Merkle Root\n     */\n    function proofRoot(uint256 index, bytes32 leaf, bytes32[] memory proof, uint256 height)\n        internal\n        pure\n        returns (bytes32 root_)\n    {\n        // Proof length could not exceed the tree height\n        uint256 proofLen = proof.length;\n        if (proofLen \u003e height) revert TreeHeightTooLow();\n        root_ = leaf;\n        /// @dev Apply unchecked to all ++h operations\n        unchecked {\n            // Go up the tree levels from the leaf following the proof\n            for (uint256 h = 0; h \u003c proofLen; ++h) {\n                // Get a sibling node on current level: this is proof[h]\n                root_ = getParent(root_, proof[h], index, h);\n            }\n            // Go up to the root: the remaining siblings are EMPTY\n            for (uint256 h = proofLen; h \u003c height; ++h) {\n                root_ = getParent(root_, bytes32(0), index, h);\n            }\n        }\n    }\n\n    /**\n     * @notice Calculates the parent of a node on the path from one of the leafs to root.\n     * @param node          Node on a path from tree leaf to root\n     * @param sibling       Sibling for a given node\n     * @param leafIndex     Index of the tree leaf\n     * @param nodeHeight    \"Level height\" for `node` (ZERO for leafs, ORIGIN_TREE_HEIGHT for root)\n     */\n    function getParent(bytes32 node, bytes32 sibling, uint256 leafIndex, uint256 nodeHeight)\n        internal\n        pure\n        returns (bytes32 parent)\n    {\n        // Index for `node` on its \"tree level\" is (leafIndex / 2**height)\n        // \"Left child\" has even index, \"right child\" has odd index\n        if ((leafIndex \u003e\u003e nodeHeight) \u0026 1 == 0) {\n            // Left child\n            return getParent(node, sibling);\n        } else {\n            // Right child\n            return getParent(sibling, node);\n        }\n    }\n\n    /// @notice Calculates the parent of tow nodes in the merkle tree.\n    /// @dev We use implementation with H(0,0) = 0\n    /// This makes EVERY empty node in the tree equal to ZERO,\n    /// saving us from storing H(0,0), H(H(0,0), H(0, 0)), and so on\n    /// @param leftChild    Left child of the calculated node\n    /// @param rightChild   Right child of the calculated node\n    /// @return parent      Value for the node having above mentioned children\n    function getParent(bytes32 leftChild, bytes32 rightChild) internal pure returns (bytes32 parent) {\n        if (leftChild == bytes32(0) \u0026\u0026 rightChild == bytes32(0)) {\n            return 0;\n        } else {\n            return keccak256(bytes.concat(leftChild, rightChild));\n        }\n    }\n\n    // ════════════════════════════════ ROOT/PROOF CALCULATION FOR A LIST OF LEAFS ═════════════════════════════════════\n\n    /**\n     * @notice Calculates merkle root for a list of given leafs.\n     * Merkle Tree is constructed by padding the list with ZERO values for leafs until list length is `2**height`.\n     * Merkle Root is calculated for the constructed tree, and then saved in `leafs[0]`.\n     * \u003e Note:\n     * \u003e - `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * \u003e - Caller is expected not to reuse `hashes` list after the call, and only use `leafs[0]` value,\n     * which is guaranteed to contain the calculated merkle root.\n     * \u003e - root is calculated using the `H(0,0) = 0` Merkle Tree implementation. See MerkleTree.sol for details.\n     * @dev Amount of leaves should be at most `2**height`\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param height    Height of the Merkle Tree to construct\n     */\n    function calculateRoot(bytes32[] memory hashes, uint256 height) internal pure {\n        uint256 levelLength = hashes.length;\n        // Amount of hashes could not exceed amount of leafs in tree with the given height\n        if (levelLength \u003e (1 \u003c\u003c height)) revert TreeHeightTooLow();\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\": the amount of iterations for the for loop above.\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n            }\n        }\n    }\n\n    /**\n     * @notice Generates a proof of inclusion of a leaf in the list. If the requested index is outside\n     * of the list range, generates a proof of inclusion for an empty leaf (proof of non-inclusion).\n     * The Merkle Tree is constructed by padding the list with ZERO values until list length is a power of two\n     * __AND__ index is in the extended list range. For example:\n     *  - `hashes.length == 6` and `0 \u003c= index \u003c= 7` will \"extend\" the list to 8 entries.\n     *  - `hashes.length == 6` and `7 \u003c index \u003c= 15` will \"extend\" the list to 16 entries.\n     * \u003e Note: `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * Caller is expected not to reuse `hashes` list after the call.\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param index     Leaf index to generate the proof for\n     * @return proof    Generated merkle proof\n     */\n    function calculateProof(bytes32[] memory hashes, uint256 index) internal pure returns (bytes32[] memory proof) {\n        // Use only meaningful values for the shortened proof\n        // Check if index is within the list range (we want to generates proofs for outside leafs as well)\n        uint256 height = getHeight(index \u003c hashes.length ? hashes.length : (index + 1));\n        proof = new bytes32[](height);\n        uint256 levelLength = hashes.length;\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Use sibling for the merkle proof; `index^1` is index of our sibling\n                proof[h] = (index ^ 1 \u003c levelLength) ? hashes[index ^ 1] : bytes32(0);\n\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\"\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n                // Traverse to parent node\n                index \u003e\u003e= 1;\n            }\n        }\n    }\n\n    /// @notice Returns the height of the tree having a given amount of leafs.\n    function getHeight(uint256 leafs) internal pure returns (uint256 height) {\n        uint256 amount = 1;\n        while (amount \u003c leafs) {\n            unchecked {\n                ++height;\n            }\n            amount \u003c\u003c= 1;\n        }\n    }\n}\n\n// contracts/libs/stack/GasData.sol\n\n/// GasData in encoded data with \"basic information about gas prices\" for some chain.\ntype GasData is uint96;\n\nusing GasDataLib for GasData global;\n\n/// ChainGas is encoded data with given chain's \"basic information about gas prices\".\ntype ChainGas is uint128;\n\nusing GasDataLib for ChainGas global;\n\n/// Library for encoding and decoding GasData and ChainGas structs.\n/// # GasData\n/// `GasData` is a struct to store the \"basic information about gas prices\", that could\n/// be later used to approximate the cost of a message execution, and thus derive the\n/// minimal tip values for sending a message to the chain.\n/// \u003e - `GasData` is supposed to be cached by `GasOracle` contract, allowing to store the\n/// \u003e approximates instead of the exact values, and thus save on storage costs.\n/// \u003e - For instance, if `GasOracle` only updates the values on +- 10% change, having an\n/// \u003e 0.4% error on the approximates would be acceptable.\n/// `GasData` is supposed to be included in the Origin's state, which are synced across\n/// chains using Agent-signed snapshots and attestations.\n/// ## GasData stack layout (from highest bits to lowest)\n///\n/// | Position   | Field        | Type   | Bytes | Description                                         |\n/// | ---------- | ------------ | ------ | ----- | --------------------------------------------------- |\n/// | (012..010] | gasPrice     | uint16 | 2     | Gas price for the chain (in Wei per gas unit)       |\n/// | (010..008] | dataPrice    | uint16 | 2     | Calldata price (in Wei per byte of content)         |\n/// | (008..006] | execBuffer   | uint16 | 2     | Tx fee safety buffer for message execution (in Wei) |\n/// | (006..004] | amortAttCost | uint16 | 2     | Amortized cost for attestation submission (in Wei)  |\n/// | (004..002] | etherPrice   | uint16 | 2     | Chain's Ether Price / Mainnet Ether Price (in BWAD) |\n/// | (002..000] | markup       | uint16 | 2     | Markup for the message execution (in BWAD)          |\n/// \u003e See Number.sol for more details on `Number` type and BWAD (binary WAD) math.\n///\n/// ## ChainGas stack layout (from highest bits to lowest)\n///\n/// | Position   | Field   | Type   | Bytes | Description      |\n/// | ---------- | ------- | ------ | ----- | ---------------- |\n/// | (016..004] | gasData | uint96 | 12    | Chain's gas data |\n/// | (004..000] | domain  | uint32 | 4     | Chain's domain   |\nlibrary GasDataLib {\n    /// @dev Amount of bits to shift to gasPrice field\n    uint96 private constant SHIFT_GAS_PRICE = 10 * 8;\n    /// @dev Amount of bits to shift to dataPrice field\n    uint96 private constant SHIFT_DATA_PRICE = 8 * 8;\n    /// @dev Amount of bits to shift to execBuffer field\n    uint96 private constant SHIFT_EXEC_BUFFER = 6 * 8;\n    /// @dev Amount of bits to shift to amortAttCost field\n    uint96 private constant SHIFT_AMORT_ATT_COST = 4 * 8;\n    /// @dev Amount of bits to shift to etherPrice field\n    uint96 private constant SHIFT_ETHER_PRICE = 2 * 8;\n\n    /// @dev Amount of bits to shift to gasData field\n    uint128 private constant SHIFT_GAS_DATA = 4 * 8;\n\n    // ═════════════════════════════════════════════════ GAS DATA ══════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded GasData struct with the given fields.\n    /// @param gasPrice_        Gas price for the chain (in Wei per gas unit)\n    /// @param dataPrice_       Calldata price (in Wei per byte of content)\n    /// @param execBuffer_      Tx fee safety buffer for message execution (in Wei)\n    /// @param amortAttCost_    Amortized cost for attestation submission (in Wei)\n    /// @param etherPrice_      Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n    /// @param markup_          Markup for the message execution (in BWAD)\n    function encodeGasData(\n        Number gasPrice_,\n        Number dataPrice_,\n        Number execBuffer_,\n        Number amortAttCost_,\n        Number etherPrice_,\n        Number markup_\n    ) internal pure returns (GasData) {\n        // Number type wraps uint16, so could safely be casted to uint96\n        // forgefmt: disable-next-item\n        return GasData.wrap(\n            uint96(Number.unwrap(gasPrice_)) \u003c\u003c SHIFT_GAS_PRICE |\n            uint96(Number.unwrap(dataPrice_)) \u003c\u003c SHIFT_DATA_PRICE |\n            uint96(Number.unwrap(execBuffer_)) \u003c\u003c SHIFT_EXEC_BUFFER |\n            uint96(Number.unwrap(amortAttCost_)) \u003c\u003c SHIFT_AMORT_ATT_COST |\n            uint96(Number.unwrap(etherPrice_)) \u003c\u003c SHIFT_ETHER_PRICE |\n            uint96(Number.unwrap(markup_))\n        );\n    }\n\n    /// @notice Wraps padded uint256 value into GasData struct.\n    function wrapGasData(uint256 paddedGasData) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(paddedGasData));\n    }\n\n    /// @notice Returns the gas price, in Wei per gas unit.\n    function gasPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_GAS_PRICE));\n    }\n\n    /// @notice Returns the calldata price, in Wei per byte of content.\n    function dataPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_DATA_PRICE));\n    }\n\n    /// @notice Returns the tx fee safety buffer for message execution, in Wei.\n    function execBuffer(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_EXEC_BUFFER));\n    }\n\n    /// @notice Returns the amortized cost for attestation submission, in Wei.\n    function amortAttCost(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_AMORT_ATT_COST));\n    }\n\n    /// @notice Returns the ratio of Chain's Ether Price / Mainnet Ether Price, in BWAD math.\n    function etherPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_ETHER_PRICE));\n    }\n\n    /// @notice Returns the markup for the message execution, in BWAD math.\n    function markup(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data)));\n    }\n\n    // ════════════════════════════════════════════════ CHAIN DATA ═════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded ChainGas struct with the given fields.\n    /// @param gasData_ Chain's gas data\n    /// @param domain_  Chain's domain\n    function encodeChainGas(GasData gasData_, uint32 domain_) internal pure returns (ChainGas) {\n        // GasData type wraps uint96, so could safely be casted to uint128\n        return ChainGas.wrap(uint128(GasData.unwrap(gasData_)) \u003c\u003c SHIFT_GAS_DATA | uint128(domain_));\n    }\n\n    /// @notice Wraps padded uint256 value into ChainGas struct.\n    function wrapChainGas(uint256 paddedChainGas) internal pure returns (ChainGas) {\n        // Casting to uint128 will truncate the highest bits, which is the behavior we want\n        return ChainGas.wrap(uint128(paddedChainGas));\n    }\n\n    /// @notice Returns the chain's gas data.\n    function gasData(ChainGas data) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(ChainGas.unwrap(data) \u003e\u003e SHIFT_GAS_DATA));\n    }\n\n    /// @notice Returns the chain's domain.\n    function domain(ChainGas data) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(ChainGas.unwrap(data));\n    }\n\n    /// @notice Returns the hash for the list of ChainGas structs.\n    function snapGasHash(ChainGas[] memory snapGas) internal pure returns (bytes32 snapGasHash_) {\n        // Use assembly to calculate the hash of the array without copying it\n        // ChainGas takes a single word of storage, thus ChainGas[] is stored in the following way:\n        // 0x00: length of the array, in words\n        // 0x20: first ChainGas struct\n        // 0x40: second ChainGas struct\n        // And so on...\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Find the location where the array data starts, we add 0x20 to skip the length field\n            let loc := add(snapGas, 0x20)\n            // Load the length of the array (in words).\n            // Shifting left 5 bits is equivalent to multiplying by 32: this converts from words to bytes.\n            let len := shl(5, mload(snapGas))\n            // Calculate the hash of the array\n            snapGasHash_ := keccak256(loc, len)\n        }\n    }\n}\n\n// contracts/libs/stack/Header.sol\n\n/// Header is encoded data with \"general routing information\".\ntype Header is uint136;\n\nusing HeaderLib for Header global;\n\n/// Types of messages supported by Origin-Destination\n/// - Base: message sent by protocol user, contains tips\n/// - Manager: message sent between AgentManager contracts located on different chains, no tips\nenum MessageFlag {\n    Base,\n    Manager\n}\n\nusing HeaderLib for MessageFlag global;\n\n/// Library for formatting _the header part_ of _the messages used by Origin and Destination_.\n/// - Header represents general information for routing a Message for Origin and Destination.\n/// - Header occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n///\n/// # Header stack layout (from highest bits to lowest)\n///\n/// | Position   | Field            | Type   | Bytes | Description                             |\n/// | ---------- | ---------------- | ------ | ----- | --------------------------------------- |\n/// | (017..016] | flag             | uint8  | 1     | Flag specifying the type of message     |\n/// | (016..012] | origin           | uint32 | 4     | Domain where message originated         |\n/// | (012..008] | nonce            | uint32 | 4     | Message nonce on the origin domain      |\n/// | (008..004] | destination      | uint32 | 4     | Domain where message will be executed   |\n/// | (004..000] | optimisticPeriod | uint32 | 4     | Optimistic period that will be enforced |\nlibrary HeaderLib {\n    /// @dev Amount of bits to shift to flag field\n    uint136 private constant SHIFT_FLAG = 16 * 8;\n    /// @dev Amount of bits to shift to origin field\n    uint136 private constant SHIFT_ORIGIN = 12 * 8;\n    /// @dev Amount of bits to shift to nonce field\n    uint136 private constant SHIFT_NONCE = 8 * 8;\n    /// @dev Amount of bits to shift to destination field\n    uint136 private constant SHIFT_DESTINATION = 4 * 8;\n\n    /// @notice Returns an encoded header with provided fields\n    /// @param origin_              Domain of origin chain\n    /// @param nonce_               Message nonce on origin chain\n    /// @param destination_         Domain of destination chain\n    /// @param optimisticPeriod_    Optimistic period for message execution\n    function encodeHeader(\n        MessageFlag flag_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint32 destination_,\n        uint32 optimisticPeriod_\n    ) internal pure returns (Header) {\n        // All casts below are upcasts, so they are safe\n        // forgefmt: disable-next-item\n        return Header.wrap(\n            uint136(uint8(flag_)) \u003c\u003c SHIFT_FLAG |\n            uint136(origin_) \u003c\u003c SHIFT_ORIGIN |\n            uint136(nonce_) \u003c\u003c SHIFT_NONCE |\n            uint136(destination_) \u003c\u003c SHIFT_DESTINATION |\n            uint136(optimisticPeriod_)\n        );\n    }\n\n    /// @notice Checks that the header is a valid encoded header.\n    function isHeader(uint256 paddedHeader) internal pure returns (bool) {\n        // Check that flag is within range\n        return _flag(paddedHeader) \u003c= uint8(type(MessageFlag).max);\n    }\n\n    /// @notice Wraps the padded encoded request into a Header-typed value.\n    /// @dev The \"padded\" header is simply an encoded header casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded headers\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedHeader) internal pure returns (Header) {\n        // Check that flag is within range\n        if (!isHeader(paddedHeader)) revert FlagOutOfRange();\n        // Casting to uint136 will truncate the highest bits, which is the behavior we want\n        return Header.wrap(uint136(paddedHeader));\n    }\n\n    /// @notice Returns header's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Header header) internal pure returns (bytes32 hashedHeader) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store header in scratch space\n            mstore(0, header)\n            // Compute hash of header padded to 32 bytes\n            hashedHeader := keccak256(0, 32)\n        }\n    }\n\n    // ══════════════════════════════════════════════ HEADER SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns header's flag field\n    function flag(Header header) internal pure returns (MessageFlag) {\n        // We check that flag is within range when wrapping the header, so this cast is safe\n        return MessageFlag(_flag(Header.unwrap(header)));\n    }\n\n    /// @notice Returns header's origin field\n    function origin(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_ORIGIN);\n    }\n\n    /// @notice Returns header's nonce field\n    function nonce(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_NONCE);\n    }\n\n    /// @notice Returns header's destination field\n    function destination(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_DESTINATION);\n    }\n\n    /// @notice Returns header's optimistic seconds field\n    function optimisticPeriod(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns header's flag field without casting to MessageFlag\n    function _flag(uint256 paddedHeader) private pure returns (uint8) {\n        // Casting to uint8 will truncate the highest bits, which is the behavior we want\n        return uint8(paddedHeader \u003e\u003e SHIFT_FLAG);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n     * constructor.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall \u0026\u0026 _initialized \u003c 1) || (!AddressUpgradeable.isContract(address(this)) \u0026\u0026 _initialized == 1),\n            \"Initializable: contract is already initialized\"\n        );\n        _initialized = 1;\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: setting the version to 255 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing \u0026\u0026 _initialized \u003c version, \"Initializable: contract is already initialized\");\n        _initialized = version;\n        _initializing = true;\n        _;\n        _initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        require(_initializing, \"Initializable: contract is not initializing\");\n        _;\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized != type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint8) {\n        return _initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _initializing;\n    }\n}\n\n// contracts/interfaces/IAgentManager.sol\n\ninterface IAgentManager {\n    /**\n     * @notice Allows Inbox to open a Dispute between a Guard and a Notary, if they are both not in Dispute already.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Guard or Notary is already in Dispute.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Allows Inbox to slash an agent, if their fraud was proven.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Domain doesn't match the saved agent domain.\n     * @param domain    Domain where the Agent is active\n     * @param agent     Address of the Agent\n     * @param prover    Address that initially provided fraud proof\n     */\n    function slashAgent(uint32 domain, address agent, address prover) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest known root of the Agent Merkle Tree.\n     */\n    function agentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns the number of opened Disputes.\n     * @dev This includes the Disputes that have been resolved already.\n     */\n    function getDisputesAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns information about the dispute with the given index.\n     * @dev Will revert if dispute with given index hasn't been opened yet.\n     * @param index             Dispute index\n     * @return guard            Address of the Guard in the Dispute\n     * @return notary           Address of the Notary in the Dispute\n     * @return slashedAgent     Address of the Agent who was slashed when Dispute was resolved\n     * @return fraudProver      Address who provided fraud proof to resolve the Dispute\n     * @return reportPayload    Raw payload with report data that led to the Dispute\n     * @return reportSignature  Guard signature for the report payload\n     */\n    function getDispute(uint256 index)\n        external\n        view\n        returns (\n            address guard,\n            address notary,\n            address slashedAgent,\n            address fraudProver,\n            bytes memory reportPayload,\n            bytes memory reportSignature\n        );\n\n    /**\n     * @notice Returns the current Dispute status of a given agent. See Structures.sol for details.\n     * @dev Every returned value will be set to zero if agent was not slashed and is not in Dispute.\n     * `rival` and `disputePtr` will be set to zero if the agent was slashed without being in Dispute.\n     * @param agent         Agent address\n     * @return flag         Flag describing the current Dispute status for the agent: None/Pending/Slashed\n     * @return rival        Address of the rival agent in the Dispute\n     * @return fraudProver  Address who provided fraud proof to resolve the Dispute\n     * @return disputePtr   Index of the opened Dispute PLUS ONE. Zero if agent is not in Dispute.\n     */\n    function disputeStatus(address agent)\n        external\n        view\n        returns (DisputeFlag flag, address rival, address fraudProver, uint256 disputePtr);\n}\n\n// contracts/interfaces/IAgentSecured.sol\n\ninterface IAgentSecured {\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * between a Guard and a Notary has been opened.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * has been resolved due to one of the agents being slashed.\n     * \u003e `rivalIndex` will be ZERO, if the slashed agent was not in the Dispute.\n     * @param slashedIndex  Index of the slashed agent in the Agent Merkle Tree\n     * @param rivalIndex    Index of the their Dispute Rival in the Agent Merkle Tree\n     */\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the address of the local AgentManager contract, which is treated as\n     * the \"source of truth\" for agent statuses.\n     */\n    function agentManager() external view returns (address);\n\n    /**\n     * @notice Returns the address of the local Inbox contract, which is treated as\n     * the \"source of truth\" for agent-signed statements.\n     * @dev Inbox passes verified agent statements to `IAgentSecured` contract.\n     */\n    function inbox() external view returns (address);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns (flag, openedAt, resolvedAt) that describes the latest status of\n     * the latest dispute for an agent with a given index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param agentIndex    Agent index in the Agent Merkle Tree\n     * @return              Latest dispute status for the given agent: (flag, openedAt, resolvedAt)\n     */\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory);\n}\n\n// contracts/libs/memory/ByteString.sol\n\n/// @dev CallData is a memory view over the payload to be used for an external call, i.e.\n/// recipient.call(callData). Its length is always (4 + 32 * N) bytes:\n/// - First 4 bytes represent the function selector.\n/// - 32 * N bytes represent N words that function arguments occupy.\ntype CallData is uint256;\n\n/// @dev Attach library functions to CallData\nusing ByteString for CallData global;\n\n/// @dev Signature is a memory view over a \"65 bytes\" array representing a ECDSA signature.\ntype Signature is uint256;\n\n/// @dev Attach library functions to Signature\nusing ByteString for Signature global;\n\nlibrary ByteString {\n    using MemViewLib for bytes;\n\n    /**\n     * @dev non-compact ECDSA signatures are enforced as of OZ 4.7.3\n     *\n     *      Signature payload memory layout\n     * [000 .. 032) r   bytes32 32 bytes\n     * [032 .. 064) s   bytes32 32 bytes\n     * [064 .. 065) v   uint8    1 byte\n     */\n    uint256 internal constant SIGNATURE_LENGTH = 65;\n    uint256 private constant OFFSET_R = 0;\n    uint256 private constant OFFSET_S = 32;\n    uint256 private constant OFFSET_V = 64;\n\n    /**\n     * @dev Calldata memory layout\n     * [000 .. 004) selector    bytes4  4 bytes\n     *      Optional: N function arguments\n     * [004 .. 036) arg1        bytes32 32 bytes\n     *      ..\n     * [AAA .. END) argN        bytes32 32 bytes\n     */\n    uint256 internal constant SELECTOR_LENGTH = 4;\n    uint256 private constant OFFSET_SELECTOR = 0;\n    uint256 private constant OFFSET_ARGUMENTS = SELECTOR_LENGTH;\n\n    // ═════════════════════════════════════════════════ SIGNATURE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the signature payload from the given values.\n     * @dev Using ByteString.formatSignature({r: r, s: s, v: v}) will make sure\n     * that params are given in the right order.\n     */\n    function formatSignature(bytes32 r, bytes32 s, uint8 v) internal pure returns (bytes memory) {\n        return abi.encodePacked(r, s, v);\n    }\n\n    /**\n     * @notice Returns a Signature view over for the given payload.\n     * @dev Will revert if the payload is not a signature.\n     */\n    function castToSignature(bytes memory payload) internal pure returns (Signature) {\n        return castToSignature(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Signature view.\n     * @dev Will revert if the memory view is not over a signature.\n     */\n    function castToSignature(MemView memView) internal pure returns (Signature) {\n        if (!isSignature(memView)) revert UnformattedSignature();\n        return Signature.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a signature\n     */\n    function isSignature(MemView memView) internal pure returns (bool) {\n        return memView.len() == SIGNATURE_LENGTH;\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Signature signature) internal pure returns (MemView) {\n        return MemView.wrap(Signature.unwrap(signature));\n    }\n\n    // ═════════════════════════════════════════════ SIGNATURE SLICING ═════════════════════════════════════════════════\n\n    /// @notice Unpacks signature payload into (r, s, v) parameters.\n    /// @dev Make sure to verify signature length with isSignature() beforehand.\n    function toRSV(Signature signature) internal pure returns (bytes32 r, bytes32 s, uint8 v) {\n        // Get the underlying memory view\n        MemView memView = unwrap(signature);\n        r = memView.index({index_: OFFSET_R, bytes_: 32});\n        s = memView.index({index_: OFFSET_S, bytes_: 32});\n        // Can be safely casted to uint8, since we index a single byte\n        v = uint8(memView.indexUint({index_: OFFSET_V, bytes_: 1}));\n    }\n\n    // ═════════════════════════════════════════════════ CALLDATA ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the calldata with the modified arguments:\n     * the existing arguments are prepended with the arguments from the prefix.\n     * @dev Given:\n     *  - `calldata = abi.encodeWithSelector(foo.selector, d, e);`\n     *  - `prefix = abi.encode(a, b, c);`\n     *  - `a`, `b`, `c` are arguments of static type (i.e. not dynamically sized ones)\n     *      Then:\n     *  - Function will return abi.encodeWithSelector(foo.selector, a, c, c, d, e)\n     *  - Returned calldata will trigger `foo(a, b, c, d, e)` when used for a contract call.\n     * Note: for clarification as to what types are considered static, see\n     * https://docs.soliditylang.org/en/latest/abi-spec.html#formal-specification-of-the-encoding\n     * @param callData  Calldata that needs to be modified\n     * @param prefix    ABI-encoded arguments to use as the first arguments in the new calldata\n     * @return Modified calldata having prefix as the first arguments.\n     */\n    function addPrefix(CallData callData, bytes memory prefix) internal view returns (bytes memory) {\n        // Prefix should occupy a whole amount of words in memory\n        if (!_fullWords(prefix.length)) revert UnformattedCallDataPrefix();\n        MemView[] memory views = new MemView[](3);\n        // Use payload's function selector\n        views[0] = abi.encodePacked(callData.callSelector()).ref();\n        // Use prefix as the first arguments\n        views[1] = prefix.ref();\n        // Use payload's remaining arguments\n        views[2] = callData.arguments();\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a CallData view over for the given payload.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(bytes memory payload) internal pure returns (CallData) {\n        return castToCallData(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a CallData view.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(MemView memView) internal pure returns (CallData) {\n        if (!isCallData(memView)) revert UnformattedCallData();\n        return CallData.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a valid calldata, i.e.\n     * a function selector, followed by arbitrary amount of arguments.\n     */\n    function isCallData(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Calldata should at least have a function selector\n        if (length \u003c SELECTOR_LENGTH) return false;\n        // The remainder of the calldata should be exactly N memory words (N \u003e= 0)\n        return _fullWords(length - SELECTOR_LENGTH);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(CallData callData) internal pure returns (MemView) {\n        return MemView.wrap(CallData.unwrap(callData));\n    }\n\n    /// @notice Returns callData's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(CallData callData) internal pure returns (bytes32) {\n        return callData.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ CALLDATA SLICING ══════════════════════════════════════════════════\n\n    /**\n     * @notice Returns amount of memory words (32 byte chunks) the function arguments\n     * occupy in the calldata.\n     * @dev This might differ from amount of arguments supplied, if any of the arguments\n     * occupies more than one memory slot. It is true, however, that argument part of the payload\n     * occupies exactly N words, even for dynamic types like `bytes`\n     */\n    function argumentWords(CallData callData) internal pure returns (uint256) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        // Equivalent of (length - SELECTOR_LENGTH) / 32\n        return (memView.len() - SELECTOR_LENGTH) \u003e\u003e 5;\n    }\n\n    /// @notice Returns selector for the provided calldata.\n    function callSelector(CallData callData) internal pure returns (bytes4) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return bytes4(memView.index({index_: OFFSET_SELECTOR, bytes_: SELECTOR_LENGTH}));\n    }\n\n    /// @notice Returns abi encoded arguments for the provided calldata.\n    function arguments(CallData callData) internal pure returns (MemView) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return memView.sliceFrom({index_: OFFSET_ARGUMENTS});\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if length is full amount of memory words (32 bytes).\n    function _fullWords(uint256 length) internal pure returns (bool) {\n        // The equivalent of length % 32 == 0\n        return length \u0026 31 == 0;\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n    function __Context_init() internal onlyInitializing {\n    }\n\n    function __Context_init_unchained() internal onlyInitializing {\n    }\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[50] private __gap;\n}\n\n// contracts/libs/merkle/MerkleTree.sol\n\n/// `BaseTree` is a struct representing incremental merkle tree.\n/// - Contains only the current branch.\n/// - The number of inserted leaves is stored externally, and is later supplied for tree operations.\n/// - Has a fixed height of `ORIGIN_TREE_HEIGHT`.\n/// - Can store up to `2 ** ORIGIN_TREE_HEIGHT - 1` leaves.\n/// \u003e Note: the hash function for the tree `H(x, y)` is defined as:\n/// \u003e - `H(0,0) = 0`\n/// \u003e - `H(x,y) = keccak256(x, y), when (x != 0 || y != 0)`\n/// ## Invariant for leafs\n/// - The leftmost empty leaf has `index == count`, where `count` is the amount of the inserted leafs so far.\n/// - Value for any empty leaf or node is bytes32(0).\n/// ## Invariant for current branch\n/// `branch[i]` is always the value of a node on the i-th level.\n/// Levels are numbered from leafs to root: `0 .. ORIGIN_TREE_HEIGHT`.\n/// `branch[i]` stores the value for the node, such that:\n//  - The node is a \"left child\" (e.g. has an even index).\n/// - The node must have two non-empty children.\n/// - Out of all level's \"left child\" nodes with \"non-empty children\",\n/// the one with the biggest index (the rightmost one) is stored as `branch[i]`.\n/// \u003e __`branch` could be used to form a proof of inclusion for the first empty leaf (`index == count`).__\n/// _Here is how:_\n/// - Let's walk along the path from the \"first empty leaf\" to the root.\n/// - i-th bit of the \"first empty leaf\" index (which is equal to `count`) determines if the path's node\n/// for this i-th level is a \"left child\" or a \"right child\".\n/// - i-th bit in `count` is 0 → we are the left child on this level → sibling is the right child\n/// that does not exist yet → `proof[i] = bytes32(0)`.\n/// - i-th bit in `count` is 1 → we are the right child on this level → sibling is the left child\n/// sibling is the rightmost \"left child\" node on the level → `proof[i] = branch[i]`.\n/// \u003e Therefore `proof[i] = (count \u0026 (1 \u003c\u003c i)) == 0 ? bytes32(0) : branch[i])`\nstruct BaseTree {\n    bytes32[ORIGIN_TREE_HEIGHT] branch;\n}\n\nusing MerkleTree for BaseTree global;\n\n/// `HistoricalTree` is an incremental merkle tree keeping track of its historical merkle roots.\n/// \u003e - `roots[N]` is the root of the tree after `N` leafs were inserted\n/// \u003e - `roots[0] == bytes32(0)`\n/// @param tree     Incremental merkle tree\n/// @param roots    Historical merkle roots of the tree\nstruct HistoricalTree {\n    BaseTree tree;\n    bytes32[] roots;\n}\n\nusing MerkleTree for HistoricalTree global;\n\n/// `DynamicTree` is a struct representing a Merkle Tree with `2**AGENT_TREE_HEIGHT` leaves.\n/// - A single operation is available: update value for leaf with an arbitrary index (which might be a non-empty leaf).\n/// - This is done by requesting the proof of inclusion for the old value, which is used to both\n/// verify the old value, and calculate the new root.\n/// \u003e Based on Original idea from [ER forum post](https://ethresear.ch/t/efficient-on-chain-dynamic-merkle-tree/11054).\nstruct DynamicTree {\n    bytes32 root;\n}\n\nusing MerkleTree for DynamicTree global;\n\n/// MerkleTree is work based on Nomad's Merkle.sol, which is used under MIT OR Apache-2.0\n/// [link](https://github.com/nomad-xyz/monorepo/blob/main/packages/contracts-core/contracts/libs/Merkle.sol).\n/// With the following changes:\n/// - Adapted for Solidity 0.8.x.\n/// - Amount of tree leaves stored externally.\n/// - Added thorough documentation.\n/// - `H(0,0) = 0` optimization from [ER forum post](https://ethresear.ch/t/optimizing-sparse-merkle-trees/3751/6).\n/// \u003e Nomad's Merkle.sol is work based on eth2 deposit contract, which is used under CC0-1.0\n///[link](https://github.com/ethereum/deposit_contract/blob/dev/deposit_contract/contracts/validator_registration.v.py).\n/// With the following changes:\n/// \u003e - Implemented in Solidity 0.7.6 (eth2 deposit contract implemented in Vyper).\n/// \u003e - `H() = keccak256()` is used as the hashing function instead of `sha256()`.\nlibrary MerkleTree {\n    /// @dev For root calculation we need at least one empty leaf, thus the minus one in the formula.\n    uint256 internal constant MAX_LEAVES = 2 ** ORIGIN_TREE_HEIGHT - 1;\n\n    // ═════════════════════════════════════════════════ BASE TREE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Inserts `node` into merkle tree\n     * @dev Reverts if tree is full\n     * @param newCount  Amount of inserted leaves in the tree after the insertion (i.e. current + 1)\n     * @param node      Element to insert into tree\n     */\n    function insertBase(BaseTree storage tree, uint256 newCount, bytes32 node) internal {\n        if (newCount \u003e MAX_LEAVES) revert MerkleTreeFull();\n        // We go up the tree following the branch from the empty leaf AFTER the just inserted one.\n        // We stop when we find the first \"right child\" node.\n        // Its sibling is now the rightmost \"left child\" node that has two non-empty children.\n        // Therefore we need to update `tree.branch` value on this level.\n        // One could see that `tree.branch` value on lower and higher levels remain unchanged.\n\n        // Loop invariant: `node` is the current level's value for the branch from JUST INSERTED leaf\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            if ((newCount \u0026 1) == 1) {\n                // Found the first \"right child\" node on the branch from EMPTY leaf\n                // `node` is the value for node on branch from JUST INSERTED leaf\n                // Which in this case is the \"left child\".\n                // We update tree.branch and exit\n                tree.branch[i] = node;\n                return;\n            }\n            // On the branch from EMPTY leaf this is still a \"left child\".\n            // Meaning on branch from JUST INSERTED leaf, `node` is a right child.\n            // We compute value for `node` parent using `tree.branch` invariant:\n            // This is the rightmost \"left child\" node, which would be sibling of `node`.\n            node = MerkleMath.getParent(tree.branch[i], node);\n            // Get the parent index, and go to the next tree level\n            newCount \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n        // As the loop should always end prematurely with the `return` statement,\n        // this code should be unreachable. We assert `false` just to be safe.\n        assert(false);\n    }\n\n    /**\n     * @notice Calculates and returns current root of the merkle tree.\n     * @param count     Current amount of inserted leaves in the tree\n     * @return current  Calculated root of `tree`\n     */\n    function rootBase(BaseTree storage tree, uint256 count) internal view returns (bytes32 current) {\n        // To calculate the root we follow the branch of first EMPTY leaf (index == count)\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            // Check if we are the left or the right child on the current level\n            if ((count \u0026 1) == 1) {\n                // We are the right child. Our sibling is the \"rightmost\" \"left-child\" node\n                // that has two non-empty children → sibling is `tree.branch[i]`\n                current = MerkleMath.getParent(tree.branch[i], current);\n            } else {\n                // We are the left child. Our sibling does not exist yet → sibling is EMPTY\n                current = MerkleMath.getParent(current, bytes32(0));\n            }\n            // Get the parent index, and go to the next tree level\n            count \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    // ══════════════════════════════════════════════ HISTORICAL TREE ══════════════════════════════════════════════════\n\n    /// @notice Initializes the historical roots for the tree by inserting an empty root.\n    // solhint-disable-next-line ordering\n    function initializeRoots(HistoricalTree storage tree) internal returns (bytes32 savedRoot) {\n        // This should only be called once, when the contract is initialized\n        assert(tree.roots.length == 0);\n        // Save root for empty merkle tree: bytes32(0)\n        tree.roots.push(savedRoot);\n    }\n\n    /// @notice Inserts a new leaf into the merkle tree.\n    /// @dev Reverts if tree is full.\n    /// @param node         Element to insert into tree\n    /// @return newRoot     Merkle root after the leaf was inserted\n    function insert(HistoricalTree storage tree, bytes32 node) internal returns (bytes32 newRoot) {\n        // Tree count after the new leaf will be inserted (we store roots[0] as root of empty tree)\n        uint256 newCount = tree.roots.length;\n        tree.tree.insertBase(newCount, node);\n        // Save the new root\n        newRoot = tree.tree.rootBase(newCount);\n        tree.roots.push(newRoot);\n    }\n\n    /// @notice Returns the historical root of the merkle tree.\n    /// @dev Reverts if not enough leafs have been inserted.\n    /// @param count            Amount of leafs in the tree at some point of time\n    /// @return historicalRoot  Merkle root after `count` leafs were inserted\n    function root(HistoricalTree storage tree, uint256 count) internal view returns (bytes32 historicalRoot) {\n        if (count \u003e= tree.roots.length) revert NotEnoughLeafs();\n        return tree.roots[count];\n    }\n\n    // ═══════════════════════════════════════════════ DYNAMIC TREE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Updates the value for the leaf with the given index in the Dynamic Merkle Tree.\n     * @dev Will revert if incorrect proof of inclusion for old value is supplied.\n     * @param tree          Dynamic merkle tree\n     * @param index         Index of the leaf to update\n     * @param oldValue      Previous value of the leaf\n     * @param branch        Proof of inclusion of previous value into the tree\n     * @param newValue      New leaf value to assign\n     * @return newRoot      New value for the Merkle Root after the leaf is updated\n     */\n    function update(\n        DynamicTree storage tree,\n        uint256 index,\n        bytes32 oldValue,\n        bytes32[] memory branch,\n        bytes32 newValue\n    ) internal returns (bytes32 newRoot) {\n        // Check that the old value + proof result in a correct root\n        if (MerkleMath.proofRoot(index, oldValue, branch, AGENT_TREE_HEIGHT) != tree.root) {\n            revert LeafNotProven();\n        }\n        // New root is new value + the same proof (values for sibling nodes are not updated)\n        newRoot = MerkleMath.proofRoot(index, newValue, branch, AGENT_TREE_HEIGHT);\n        // Write the new root\n        tree.root = newRoot;\n    }\n}\n\n// contracts/libs/stack/Tips.sol\n\n/// Tips is encoded data with \"tips paid for sending a base message\".\n/// Note: even though uint256 is also an underlying type for MemView, Tips is stored ON STACK.\ntype Tips is uint256;\n\nusing TipsLib for Tips global;\n\n/// # Tips\n/// Library for formatting _the tips part_ of _the base messages_.\n///\n/// ## How the tips are awarded\n/// Tips are paid for sending a base message, and are split across all the agents that\n/// made the message execution on destination chain possible.\n/// ### Summit tips\n/// Split between:\n///     - Guard posting a snapshot with state ST_G for the origin chain.\n///     - Notary posting a snapshot SN_N using ST_G. This creates attestation A.\n///     - Notary posting a message receipt after it is executed on destination chain.\n/// ### Attestation tips\n/// Paid to:\n///     - Notary posting attestation A to destination chain.\n/// ### Execution tips\n/// Paid to:\n///     - First executor performing a valid execution attempt (correct proofs, optimistic period over),\n///      using attestation A to prove message inclusion on origin chain, whether the recipient reverted or not.\n/// ### Delivery tips.\n/// Paid to:\n///     - Executor who successfully executed the message on destination chain.\n///\n/// ## Tips encoding\n/// - Tips occupy a single storage word, and thus are stored on stack instead of being stored in memory.\n/// - The actual tip values should be determined by multiplying stored values by divided by TIPS_MULTIPLIER=2**32.\n/// - Tips are packed into a single word of storage, while allowing real values up to ~8*10**28 for every tip category.\n/// \u003e The only downside is that the \"real tip values\" are now multiplies of ~4*10**9, which should be fine even for\n/// the chains with the most expensive gas currency.\n/// # Tips stack layout (from highest bits to lowest)\n///\n/// | Position   | Field          | Type   | Bytes | Description                                                |\n/// | ---------- | -------------- | ------ | ----- | ---------------------------------------------------------- |\n/// | (032..024] | summitTip      | uint64 | 8     | Tip for agents interacting with Summit contract            |\n/// | (024..016] | attestationTip | uint64 | 8     | Tip for Notary posting attestation to Destination contract |\n/// | (016..008] | executionTip   | uint64 | 8     | Tip for valid execution attempt on destination chain       |\n/// | (008..000] | deliveryTip    | uint64 | 8     | Tip for successful message delivery on destination chain   |\n\nlibrary TipsLib {\n    using SafeCast for uint256;\n\n    /// @dev Amount of bits to shift to summitTip field\n    uint256 private constant SHIFT_SUMMIT_TIP = 24 * 8;\n    /// @dev Amount of bits to shift to attestationTip field\n    uint256 private constant SHIFT_ATTESTATION_TIP = 16 * 8;\n    /// @dev Amount of bits to shift to executionTip field\n    uint256 private constant SHIFT_EXECUTION_TIP = 8 * 8;\n\n    // ═══════════════════════════════════════════════════ TIPS ════════════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips with the given fields\n    /// @param summitTip_        Tip for agents interacting with Summit contract, divided by TIPS_MULTIPLIER\n    /// @param attestationTip_   Tip for Notary posting attestation to Destination contract, divided by TIPS_MULTIPLIER\n    /// @param executionTip_     Tip for valid execution attempt on destination chain, divided by TIPS_MULTIPLIER\n    /// @param deliveryTip_      Tip for successful message delivery on destination chain, divided by TIPS_MULTIPLIER\n    function encodeTips(uint64 summitTip_, uint64 attestationTip_, uint64 executionTip_, uint64 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // forgefmt: disable-next-item\n        return Tips.wrap(\n            uint256(summitTip_) \u003c\u003c SHIFT_SUMMIT_TIP |\n            uint256(attestationTip_) \u003c\u003c SHIFT_ATTESTATION_TIP |\n            uint256(executionTip_) \u003c\u003c SHIFT_EXECUTION_TIP |\n            uint256(deliveryTip_)\n        );\n    }\n\n    /// @notice Convenience function to encode tips with uint256 values.\n    function encodeTips256(uint256 summitTip_, uint256 attestationTip_, uint256 executionTip_, uint256 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // In practice, the tips amounts are not supposed to be higher than 2**96, and with 32 bits of granularity\n        // using uint64 is enough to store the values. However, we still check for overflow just in case.\n        // TODO: consider using Number type to store the tips values.\n        return encodeTips({\n            summitTip_: (summitTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            attestationTip_: (attestationTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            executionTip_: (executionTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            deliveryTip_: (deliveryTip_ \u003e\u003e TIPS_GRANULARITY).toUint64()\n        });\n    }\n\n    /// @notice Wraps the padded encoded tips into a Tips-typed value.\n    /// @dev There is no actual padding here, as the underlying type is already uint256,\n    /// but we include this function for consistency and to be future-proof, if tips will eventually use anything\n    /// smaller than uint256.\n    function wrapPadded(uint256 paddedTips) internal pure returns (Tips) {\n        return Tips.wrap(paddedTips);\n    }\n\n    /**\n     * @notice Returns a formatted Tips payload specifying empty tips.\n     * @return Formatted tips\n     */\n    function emptyTips() internal pure returns (Tips) {\n        return Tips.wrap(0);\n    }\n\n    /// @notice Returns tips's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Tips tips) internal pure returns (bytes32 hashedTips) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store tips in scratch space\n            mstore(0, tips)\n            // Compute hash of tips padded to 32 bytes\n            hashedTips := keccak256(0, 32)\n        }\n    }\n\n    // ═══════════════════════════════════════════════ TIPS SLICING ════════════════════════════════════════════════════\n\n    /// @notice Returns summitTip field\n    function summitTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_SUMMIT_TIP);\n    }\n\n    /// @notice Returns attestationTip field\n    function attestationTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_ATTESTATION_TIP);\n    }\n\n    /// @notice Returns executionTip field\n    function executionTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_EXECUTION_TIP);\n    }\n\n    /// @notice Returns deliveryTip field\n    function deliveryTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips));\n    }\n\n    // ════════════════════════════════════════════════ TIPS VALUE ═════════════════════════════════════════════════════\n\n    /// @notice Returns total value of the tips payload.\n    /// This is the sum of the encoded values, scaled up by TIPS_MULTIPLIER\n    function value(Tips tips) internal pure returns (uint256 value_) {\n        value_ = uint256(tips.summitTip()) + tips.attestationTip() + tips.executionTip() + tips.deliveryTip();\n        value_ \u003c\u003c= TIPS_GRANULARITY;\n    }\n\n    /// @notice Increases the delivery tip to match the new value.\n    function matchValue(Tips tips, uint256 newValue) internal pure returns (Tips newTips) {\n        uint256 oldValue = tips.value();\n        if (newValue \u003c oldValue) revert TipsValueTooLow();\n        // We want to increase the delivery tip, while keeping the other tips the same\n        unchecked {\n            uint256 delta = (newValue - oldValue) \u003e\u003e TIPS_GRANULARITY;\n            // `delta` fits into uint224, as TIPS_GRANULARITY is 32, so this never overflows uint256.\n            // In practice, this will never overflow uint64 as well, but we still check it just in case.\n            if (delta + tips.deliveryTip() \u003e type(uint64).max) revert TipsOverflow();\n            // Delivery tips occupy lowest 8 bytes, so we can just add delta to the tips value\n            // to effectively increase the delivery tip (knowing that delta fits into uint64).\n            newTips = Tips.wrap(Tips.unwrap(tips) + delta);\n        }\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    function __Ownable_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable_init_unchained() internal onlyInitializing {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n    function __Ownable2Step_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable2Step_init_unchained() internal onlyInitializing {\n    }\n    address private _pendingOwner;\n\n    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Returns the address of the pending owner.\n     */\n    function pendingOwner() public view virtual returns (address) {\n        return _pendingOwner;\n    }\n\n    /**\n     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual override onlyOwner {\n        _pendingOwner = newOwner;\n        emit OwnershipTransferStarted(owner(), newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual override {\n        delete _pendingOwner;\n        super._transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev The new owner accepts the ownership transfer.\n     */\n    function acceptOwnership() public virtual {\n        address sender = _msgSender();\n        require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n        _transferOwnership(sender);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// contracts/libs/memory/State.sol\n\n/// State is a memory view over a formatted state payload.\ntype State is uint256;\n\nusing StateLib for State global;\n\n/// # State\n/// State structure represents the state of Origin contract at some point of time.\n/// - State is structured in a way to track the updates of the Origin Merkle Tree.\n/// - State includes root of the Origin Merkle Tree, origin domain and some additional metadata.\n/// ## Origin Merkle Tree\n/// Hash of every sent message is inserted in the Origin Merkle Tree, which changes\n/// the value of Origin Merkle Root (which is the root for the mentioned tree).\n/// - Origin has a single Merkle Tree for all messages, regardless of their destination domain.\n/// - This leads to Origin state being updated if and only if a message was sent in a block.\n/// - Origin contract is a \"source of truth\" for states: a state is considered \"valid\" in its Origin,\n/// if it matches the state of the Origin contract after the N-th (nonce) message was sent.\n///\n/// # Memory layout of State fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                    |\n/// | ---------- | ----------- | ------- | ----- | ------------------------------ |\n/// | [000..032) | root        | bytes32 | 32    | Root of the Origin Merkle Tree |\n/// | [032..036) | origin      | uint32  | 4     | Domain where Origin is located |\n/// | [036..040) | nonce       | uint32  | 4     | Amount of sent messages        |\n/// | [040..045) | blockNumber | uint40  | 5     | Block of last sent message     |\n/// | [045..050) | timestamp   | uint40  | 5     | Time of last sent message      |\n/// | [050..062) | gasData     | uint96  | 12    | Gas data for the chain         |\n///\n/// @dev State could be used to form a Snapshot to be signed by a Guard or a Notary.\nlibrary StateLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_ROOT = 0;\n    uint256 private constant OFFSET_ORIGIN = 32;\n    uint256 private constant OFFSET_NONCE = 36;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 40;\n    uint256 private constant OFFSET_TIMESTAMP = 45;\n    uint256 private constant OFFSET_GAS_DATA = 50;\n\n    // ═══════════════════════════════════════════════════ STATE ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted State payload with provided fields\n     * @param root_         New merkle root\n     * @param origin_       Domain of Origin's chain\n     * @param nonce_        Nonce of the merkle root\n     * @param blockNumber_  Block number when root was saved in Origin\n     * @param timestamp_    Block timestamp when root was saved in Origin\n     * @param gasData_      Gas data for the chain\n     * @return Formatted state\n     */\n    function formatState(\n        bytes32 root_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_,\n        GasData gasData_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(root_, origin_, nonce_, blockNumber_, timestamp_, gasData_);\n    }\n\n    /**\n     * @notice Returns a State view over the given payload.\n     * @dev Will revert if the payload is not a state.\n     */\n    function castToState(bytes memory payload) internal pure returns (State) {\n        return castToState(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a State view.\n     * @dev Will revert if the memory view is not over a state.\n     */\n    function castToState(MemView memView) internal pure returns (State) {\n        if (!isState(memView)) revert UnformattedState();\n        return State.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted State.\n    function isState(MemView memView) internal pure returns (bool) {\n        return memView.len() == STATE_LENGTH;\n    }\n\n    /// @notice Returns the hash of a State, that could be later signed by a Guard to signal\n    /// that the state is invalid.\n    function hashInvalid(State state) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(stateInvalidSalt, keccak(state))\n        return state.unwrap().keccakSalted(STATE_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(State state) internal pure returns (MemView) {\n        return MemView.wrap(State.unwrap(state));\n    }\n\n    /// @notice Compares two State structures.\n    function equals(State a, State b) internal pure returns (bool) {\n        // Length of a State payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═══════════════════════════════════════════════ STATE HASHING ═══════════════════════════════════════════════════\n\n    /// @notice Returns the hash of the State.\n    /// @dev We are using the Merkle Root of a tree with two leafs (see below) as state hash.\n    function leaf(State state) internal pure returns (bytes32) {\n        (bytes32 leftLeaf_, bytes32 rightLeaf_) = state.subLeafs();\n        // Final hash is the parent of these leafs\n        return keccak256(bytes.concat(leftLeaf_, rightLeaf_));\n    }\n\n    /// @notice Returns \"sub-leafs\" of the State. Hash of these \"sub leafs\" is going to be used\n    /// as a \"state leaf\" in the \"Snapshot Merkle Tree\".\n    /// This enables proving that leftLeaf = (root, origin) was a part of the \"Snapshot Merkle Tree\",\n    /// by combining `rightLeaf` with the remainder of the \"Snapshot Merkle Proof\".\n    function subLeafs(State state) internal pure returns (bytes32 leftLeaf_, bytes32 rightLeaf_) {\n        MemView memView = state.unwrap();\n        // Left leaf is (root, origin)\n        leftLeaf_ = memView.prefix({len_: OFFSET_NONCE}).keccak();\n        // Right leaf is (metadata), or (nonce, blockNumber, timestamp)\n        rightLeaf_ = memView.sliceFrom({index_: OFFSET_NONCE}).keccak();\n    }\n\n    /// @notice Returns the left \"sub-leaf\" of the State.\n    function leftLeaf(bytes32 root_, uint32 origin_) internal pure returns (bytes32) {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(root_, origin_));\n    }\n\n    /// @notice Returns the right \"sub-leaf\" of the State.\n    function rightLeaf(uint32 nonce_, uint40 blockNumber_, uint40 timestamp_, GasData gasData_)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(nonce_, blockNumber_, timestamp_, gasData_));\n    }\n\n    // ═══════════════════════════════════════════════ STATE SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns a historical Merkle root from the Origin contract.\n    function root(State state) internal pure returns (bytes32) {\n        return state.unwrap().index({index_: OFFSET_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns domain of chain where the Origin contract is deployed.\n    function origin(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns nonce of Origin contract at the time, when `root` was the Merkle root.\n    function nonce(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when `root` was saved in Origin.\n    function blockNumber(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when `root` was saved in Origin.\n    /// @dev This is the timestamp according to the origin chain.\n    function timestamp(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n\n    /// @notice Returns gas data for the chain.\n    function gasData(State state) internal pure returns (GasData) {\n        return GasDataLib.wrapGasData(state.unwrap().indexUint({index_: OFFSET_GAS_DATA, bytes_: GAS_DATA_LENGTH}));\n    }\n}\n\n// contracts/libs/memory/BaseMessage.sol\n\n/// BaseMessage is a memory view over the base message supported by Origin-Destination\ntype BaseMessage is uint256;\n\nusing BaseMessageLib for BaseMessage global;\n\n/// BaseMessage structure represents a base message sent via the Origin-Destination contracts.\n/// - It only contains data relevant to the base message, the rest of data is encoded in the message header.\n/// - `sender` and `recipient` for EVM chains are EVM addresses casted to bytes32, while preserving left-alignment.\n/// - `tips` and `request` parameters are specified by a message sender\n/// \u003e Origin will calculate minimum tips for given request and content length, and will reject messages with tips\n/// lower than that.\n///\n/// # Memory layout of BaseMessage fields\n///\n/// | Position   | Field     | Type    | Bytes | Description                            |\n/// | ---------- | --------- | ------- | ----- | -------------------------------------- |\n/// | [000..032) | tips      | uint256 | 32    | Encoded tips paid on origin chain      |\n/// | [032..064) | sender    | bytes32 | 32    | Sender address on origin chain         |\n/// | [064..096) | recipient | bytes32 | 32    | Recipient address on destination chain |\n/// | [096..116) | request   | uint160 | 20    | Encoded request for message execution  |\n/// | [104..AAA) | content   | bytes   | ??    | Content to be passed to recipient      |\nlibrary BaseMessageLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_TIPS = 0;\n    uint256 private constant OFFSET_SENDER = 32;\n    uint256 private constant OFFSET_RECIPIENT = 64;\n    uint256 private constant OFFSET_REQUEST = OFFSET_RECIPIENT + TIPS_LENGTH;\n    uint256 private constant OFFSET_CONTENT = OFFSET_REQUEST + REQUEST_LENGTH;\n\n    // ═══════════════════════════════════════════════ BASE MESSAGE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted BaseMessage payload with provided fields.\n     * @param tips_         Encoded tips information\n     * @param sender_       Sender address on origin chain\n     * @param recipient_    Recipient address on destination chain\n     * @param request_      Encoded request for message execution\n     * @param content_      Raw content to be passed to recipient on destination chain\n     * @return Formatted base message\n     */\n    function formatBaseMessage(Tips tips_, bytes32 sender_, bytes32 recipient_, Request request_, bytes memory content_)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return abi.encodePacked(tips_, sender_, recipient_, request_, content_);\n    }\n\n    /**\n     * @notice Returns a BaseMessage view over the given payload.\n     * @dev Will revert if the payload is not a base message.\n     */\n    function castToBaseMessage(bytes memory payload) internal pure returns (BaseMessage) {\n        return castToBaseMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a BaseMessage view.\n     * @dev Will revert if the memory view is not over a base message payload.\n     */\n    function castToBaseMessage(MemView memView) internal pure returns (BaseMessage) {\n        if (!isBaseMessage(memView)) revert UnformattedBaseMessage();\n        return BaseMessage.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted BaseMessage.\n    function isBaseMessage(MemView memView) internal pure returns (bool) {\n        // Check if sender, recipient, tips fields exist\n        return (memView.len() \u003e= OFFSET_CONTENT);\n        // Content could be empty, so we don't check that\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(BaseMessage baseMessage) internal pure returns (MemView) {\n        return MemView.wrap(BaseMessage.unwrap(baseMessage));\n    }\n\n    /// @notice Returns baseMessage's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        // We hash \"tips\" and \"everything but tips\" to make tips proofs easier to verify\n        return MerkleMath.getParent(baseMessage.tips().leaf(), baseMessage.bodyLeaf());\n    }\n\n    /// @notice Returns hash for the \"everything but tips\" part of the base message.\n    function bodyLeaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_SENDER}).keccak();\n    }\n\n    // ═══════════════════════════════════════════ BASE MESSAGE SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips paid on origin chain.\n    function tips(BaseMessage baseMessage) internal pure returns (Tips) {\n        return TipsLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_TIPS, bytes_: TIPS_LENGTH})));\n    }\n\n    /// @notice Returns sender address on origin chain.\n    function sender(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_SENDER, bytes_: 32});\n    }\n\n    /// @notice Returns recipient address on destination chain.\n    function recipient(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_RECIPIENT, bytes_: 32});\n    }\n\n    /// @notice Returns an encoded request for message execution on destination chain.\n    function request(BaseMessage baseMessage) internal pure returns (Request) {\n        return RequestLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_REQUEST, bytes_: REQUEST_LENGTH})));\n    }\n\n    /// @notice Returns an untyped memory view over the content to be passed to recipient.\n    function content(BaseMessage baseMessage) internal pure returns (MemView) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_CONTENT});\n    }\n}\n\n// contracts/base/MessagingBase.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for all messaging contracts.\n * - Provides context on the local chain's domain.\n * - Provides ownership functionality.\n * - Will be providing pausing functionality when it is implemented.\n */\nabstract contract MessagingBase is MultiCallable, Versioned, Ownable2StepUpgradeable {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @notice Domain of the local chain, set once upon contract creation\n    uint32 public immutable localDomain;\n    // @notice Domain of the Synapse chain, set once upon contract creation\n    uint32 public immutable synapseDomain;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev gap for upgrade safety\n    uint256[50] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    constructor(string memory version_, uint32 synapseDomain_) Versioned(version_) {\n        localDomain = ChainContext.chainId();\n        synapseDomain = synapseDomain_;\n    }\n\n    // TODO: Implement pausing\n\n    /**\n     * @dev Should be impossible to renounce ownership;\n     * we override OpenZeppelin OwnableUpgradeable's\n     * implementation of renounceOwnership to make it a no-op\n     */\n    function renounceOwnership() public override onlyOwner {} //solhint-disable-line no-empty-blocks\n}\n\n// contracts/libs/memory/Message.sol\n\n/// Message is a memory over over a formatted message payload.\ntype Message is uint256;\n\nusing MessageLib for Message global;\n\n/// Library for formatting the various messages supported by Origin and Destination.\n///\n/// # Message memory layout\n///\n/// | Position   | Field  | Type    | Bytes | Description                                             |\n/// | ---------- | ------ | ------- | ----- | ------------------------------------------------------- |\n/// | [000..017) | header | uint136 | 17    | Encoded general routing information for the message     |\n/// | [017..AAA) | body   | bytes   | ??    | Formatted payload (according to flag) with message body |\nlibrary MessageLib {\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MemViewLib for bytes;\n    using HeaderLib for MemView;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_HEADER = 0;\n    uint256 private constant OFFSET_BODY = OFFSET_HEADER + HEADER_LENGTH;\n\n    // ══════════════════════════════════════════════════ MESSAGE ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns formatted message with provided fields.\n     * @param header_   Encoded general routing information for the message\n     * @param body_     Formatted payload (according to flag) with message body\n     * @return Formatted message\n     */\n    function formatMessage(Header header_, bytes memory body_) internal pure returns (bytes memory) {\n        return abi.encodePacked(header_, body_);\n    }\n\n    /**\n     * @notice Returns a Message view over for the given payload.\n     * @dev Will revert if the payload is not a message payload.\n     */\n    function castToMessage(bytes memory payload) internal pure returns (Message) {\n        return castToMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Message view.\n     * @dev Will revert if the memory view is not over a message payload.\n     */\n    function castToMessage(MemView memView) internal pure returns (Message) {\n        if (!isMessage(memView)) revert UnformattedMessage();\n        return Message.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Message.\n     */\n    function isMessage(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Check if headers exist in the payload\n        if (length \u003c OFFSET_BODY) return false;\n        // Check that Header is valid\n        uint256 paddedHeader = _header(memView);\n        if (!HeaderLib.isHeader(paddedHeader)) return false;\n        // Check that body is formatted according to the flag\n        // Only Base/Manager message flags exist\n        if (HeaderLib.wrapPadded(paddedHeader).flag() == MessageFlag.Base) {\n            // Check if body is a formatted base message\n            return _body(memView).isBaseMessage();\n        } else {\n            // Check if body is a formatted calldata for AgentManager call\n            return _body(memView).isCallData();\n        }\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Message message) internal pure returns (MemView) {\n        return MemView.wrap(Message.unwrap(message));\n    }\n\n    /// @notice Returns message's hash: a leaf to be inserted in the Merkle tree.\n    function leaf(Message message) internal pure returns (bytes32) {\n        // We hash header and body separately to make message proofs easier to verify\n        Header header_ = message.header();\n        // Only Base/Manager message flags exist\n        if (header_.flag() == MessageFlag.Base) {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToBaseMessage().leaf());\n        } else {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToCallData().leaf());\n        }\n    }\n\n    // ══════════════════════════════════════════════ MESSAGE SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns message's encoded header field.\n    function header(Message message) internal pure returns (Header) {\n        return HeaderLib.wrapPadded((message.unwrap().indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH})));\n    }\n\n    /// @notice Returns message's body field as an untyped memory view.\n    function body(Message message) internal pure returns (MemView) {\n        MemView memView = message.unwrap();\n        return _body(memView);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns message's padded header without checking that it is a valid header.\n    function _header(MemView memView) private pure returns (uint256) {\n        return memView.indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH});\n    }\n\n    /// @dev Returns an untyped memory view over the body field without checking\n    /// if the whole payload or the body are properly formatted.\n    function _body(MemView memView) private pure returns (MemView) {\n        return memView.sliceFrom({index_: OFFSET_BODY});\n    }\n}\n\n// contracts/base/AgentSecured.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for messaging contracts that are secured by the agent manager.\n * `AgentSecured` relies on `AgentManager` to provide the following functionality:\n * - Keep track of agents and their statuses.\n * - Pass agent-signed statements that were verified by the agent manager.\n * - These statements are considered valid indefinitely, unless the agent is disputed.\n * - Disputes are opened and resolved by the agent manager.\n * \u003e `AgentSecured` implementation should never use statements signed by agents that are disputed.\n */\nabstract contract AgentSecured is MessagingBase, IAgentSecured {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    address public immutable agentManager;\n\n    /// @inheritdoc IAgentSecured\n    address public immutable inbox;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    // (agent index =\u003e their dispute status: flag, openedAt, resolvedAt)\n    mapping(uint32 =\u003e DisputeStatus) internal _disputes;\n\n    /// @dev gap for upgrade safety\n    uint256[49] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    modifier onlyAgentManager() {\n        if (msg.sender != agentManager) revert CallerNotAgentManager();\n        _;\n    }\n\n    modifier onlyInbox() {\n        if (msg.sender != inbox) revert CallerNotInbox();\n        _;\n    }\n\n    constructor(string memory version_, uint32 synapseDomain_, address agentManager_, address inbox_)\n        MessagingBase(version_, synapseDomain_)\n    {\n        agentManager = agentManager_;\n        inbox = inbox_;\n    }\n\n    // ════════════════════════════════════════════ ONLY AGENT MANAGER ═════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external onlyAgentManager {\n        uint40 openedAt = ChainContext.blockTimestamp();\n        DisputeStatus memory status = DisputeStatus({flag: DisputeFlag.Pending, openedAt: openedAt, resolvedAt: 0});\n        _disputes[guardIndex] = status;\n        _disputes[notaryIndex] = status;\n    }\n\n    /// @inheritdoc IAgentSecured\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external onlyAgentManager {\n        // Update the dispute status of the slashed agent first.\n        uint40 resolvedAt = ChainContext.blockTimestamp();\n        _disputes[slashedIndex].flag = DisputeFlag.Slashed;\n        _disputes[slashedIndex].resolvedAt = resolvedAt;\n        // Mark the rival agent as not disputed, if there was an ongoing dispute.\n        if (rivalIndex != 0) {\n            _disputes[rivalIndex].flag = DisputeFlag.None;\n            _disputes[rivalIndex].resolvedAt = resolvedAt;\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function agentStatus(address agent) external view returns (AgentStatus memory) {\n        return _agentStatus(agent);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status) {\n        return _getAgent(index);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory) {\n        return _disputes[agentIndex];\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns status of the given agent: (flag, domain, index).\n    function _agentStatus(address agent) internal view returns (AgentStatus memory) {\n        return IAgentManager(agentManager).agentStatus(agent);\n    }\n\n    /// @dev Returns agent and their status for a given agent index. Returns zero values for non existing indexes.\n    function _getAgent(uint256 index) internal view returns (address agent, AgentStatus memory status) {\n        return IAgentManager(agentManager).getAgent(index);\n    }\n\n    /// @dev Checks if a Dispute exists for the given Notary. This function returns true, if\n    /// Notary is in ongoing Dispute, or if Dispute was resolved not in Notary's favor.\n    /// In both cases we can't trust Notary's data.\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeExists(uint32 notaryIndex) internal view returns (bool) {\n        return _disputes[notaryIndex].flag != DisputeFlag.None;\n    }\n\n    /// @dev Checks if a Notary recently won a Dispute and is still in the \"post-dispute\" timeout period.\n    /// In this period we still can't trust Notary's data, though we can optimistically assume that\n    /// that the data will be correct after the timeout (assuming no new Disputes are opened).\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeTimeout(uint32 notaryIndex) internal view returns (bool) {\n        DisputeStatus memory status = _disputes[notaryIndex];\n        // Exit early if Notary is in ongoing Dispute / slashed.\n        if (status.flag != DisputeFlag.None) return false;\n        // Check if Notary has been in any Dispute at all.\n        if (status.openedAt == 0) return false;\n        // Otherwise check if the Dispute timeout is still active.\n        return block.timestamp \u003c status.resolvedAt + DISPUTE_TIMEOUT_NOTARY;\n    }\n}\n\n// contracts/hubs/StateHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StateHub` is a parent contract for `Origin`. It is responsible for the following:\n/// - Keeping track of the historical Origin Merkle Tree containing all the message hashes.\n/// - Keeping track of the historical Origin States, as well as verifying their validity.\nabstract contract StateHub is AgentSecured, StateHubEvents, IStateHub {\n    using SafeCast for uint256;\n    using StateLib for bytes;\n\n    struct OriginState {\n        uint40 blockNumber;\n        uint40 timestamp;\n        GasData gasData;\n    }\n    // Bits left for tight packing: 80\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Historical Merkle Tree\n    /// Note: Takes two storage slots\n    HistoricalTree private _tree;\n\n    /// @dev All historical contract States\n    OriginState[] private _originStates;\n\n    /// @dev gap for upgrade safety\n    uint256[47] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IStateHub\n    function isValidState(bytes memory statePayload) external view returns (bool isValid) {\n        // This will revert if payload is not a formatted state\n        State state = statePayload.castToState();\n        return _isValidState(state);\n    }\n\n    /// @inheritdoc IStateHub\n    function statesAmount() external view returns (uint256) {\n        return _originStates.length;\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestLatestState() external view returns (bytes memory stateData) {\n        // This never underflows, assuming the contract was initialized\n        return suggestState(_nextNonce() - 1);\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestState(uint32 nonce) public view returns (bytes memory stateData) {\n        // This will revert if nonce is out of range\n        bytes32 root = _tree.root(nonce);\n        return _formatOriginState(_originStates[nonce], root, localDomain, nonce);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Initializes the saved states list by inserting a state for an empty Merkle Tree.\n    function _initializeStates() internal {\n        // This should only be called once, when the contract is initialized\n        // This will revert if _tree.roots is non-empty\n        bytes32 savedRoot = _tree.initializeRoots();\n        // Save root for empty merkle _tree with block number and timestamp of initialization\n        _saveState(savedRoot, _toOriginState());\n    }\n\n    /// @dev Inserts leaf into the Merkle Tree and saves the updated origin State.\n    function _insertAndSave(bytes32 leaf) internal {\n        bytes32 newRoot = _tree.insert(leaf);\n        _saveState(newRoot, _toOriginState());\n    }\n\n    /// @dev Saves an updated state of the Origin contract\n    function _saveState(bytes32 root, OriginState memory state) internal {\n        uint32 nonce = _nextNonce();\n        _originStates.push(state);\n        // Emit event with raw state data\n        emit StateSaved(_formatOriginState(state, root, localDomain, nonce));\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns nonce of the next sent message: the amount of saved States so far.\n    /// This always equals to \"total amount of sent messages\" plus 1.\n    function _nextNonce() internal view returns (uint32) {\n        // TODO: consider using more than 32 bits for origin nonces\n        return _originStates.length.toUint32();\n    }\n\n    /// @dev Checks if a state is valid, i.e. if it matches the historical one.\n    /// Reverts, if state refers to another Origin contract.\n    function _isValidState(State state) internal view returns (bool) {\n        // Check if state refers to this contract\n        if (state.origin() != localDomain) revert IncorrectOriginDomain();\n        // Check if nonce exists\n        uint32 nonce = state.nonce();\n        if (nonce \u003e= _originStates.length) return false;\n        // Check if state root matches the historical one\n        if (state.root() != _tree.root(nonce)) return false;\n        // Check if state metadata matches the historical one\n        return _areEqual(state, _originStates[nonce]);\n    }\n\n    // ═════════════════════════════════════════════ STRUCT FORMATTING ═════════════════════════════════════════════════\n\n    /// @dev Returns a formatted payload for a stored OriginState.\n    function _formatOriginState(OriginState memory originState, bytes32 root, uint32 origin, uint32 nonce)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return StateLib.formatState({\n            root_: root,\n            origin_: origin,\n            nonce_: nonce,\n            blockNumber_: originState.blockNumber,\n            timestamp_: originState.timestamp,\n            gasData_: originState.gasData\n        });\n    }\n\n    /// @dev Child contract should implement the logic for getting the current gas data from the gas oracle\n    /// to be saved as part of the Origin State.\n    // solhint-disable-next-line ordering\n    function _fetchGasData() internal view virtual returns (GasData);\n\n    /// @dev Returns a OriginState struct to save in the contract.\n    function _toOriginState() internal view returns (OriginState memory originState) {\n        originState.blockNumber = ChainContext.blockNumber();\n        originState.timestamp = ChainContext.blockTimestamp();\n        originState.gasData = _fetchGasData();\n    }\n\n    /// @dev Checks that a state and its Origin representation are equal.\n    function _areEqual(State state, OriginState memory originState) internal pure returns (bool) {\n        return state.blockNumber() == originState.blockNumber \u0026\u0026 state.timestamp() == originState.timestamp;\n    }\n}\n\n// contracts/Origin.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Origin` contract is used for sending messages to remote chains. It is done\n/// by inserting the message hashes into the Origin Merkle, which makes it possible to\n/// prove that message was sent using the Merkle proof against the Origin Merkle Root. This essentially\n/// compresses the list of messages into a single 32-byte value that needs to be stored on the destination chain.\n/// `Origin` is responsible for the following:\n/// - Formatting the sent message payloads, and inserting their hashes into the Origin Merkle Tree.\n/// - Keeping track of its own historical states (see parent contract `StateHub`).\n/// - Enforcing minimum tip values for sent base messages based on the provided execution requests.\n/// - Distributing the collected tips upon request from a local `AgentManager` contract.\ncontract Origin is StateHub, OriginEvents, InterfaceOrigin {\n    using MemViewLib for bytes;\n    using MessageLib for bytes;\n    using TipsLib for bytes;\n    using TypeCasts for address;\n\n    address public immutable gasOracle;\n\n    modifier onlyRemoteDestination(uint32 destination) {\n        if (destination == localDomain) revert IncorrectDestinationDomain();\n        _;\n    }\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_, address gasOracle_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {\n        gasOracle = gasOracle_;\n    }\n\n    /// @notice Initializes Origin contract:\n    /// - msg.sender is set as contract owner\n    /// - State of \"empty merkle tree\" is saved\n    function initialize() external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize \"states\": state of an \"empty merkle tree\" is saved\n        _initializeStates();\n    }\n\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable onlyRemoteDestination(destination) returns (uint32 messageNonce, bytes32 messageHash) {\n        // Check that content is not too large\n        if (content.length \u003e MAX_CONTENT_BYTES) revert ContentLengthTooBig();\n        // This will revert if msg.value is lower than value of minimum tips\n        Tips tips = _getMinimumTips(destination, paddedRequest, content.length).matchValue(msg.value);\n        Request request = RequestLib.wrapPadded(paddedRequest);\n        // Format the BaseMessage body\n        bytes memory body = BaseMessageLib.formatBaseMessage({\n            sender_: msg.sender.addressToBytes32(),\n            recipient_: recipient,\n            tips_: tips,\n            request_: request,\n            content_: content\n        });\n        // Send the message\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Base, body);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        onlyAgentManager\n        onlyRemoteDestination(destination)\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // AgentManager (checked via modifier) is responsible for constructing the calldata payload correctly.\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Manager, payload);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function withdrawTips(address recipient, uint256 amount) external onlyAgentManager {\n        if (address(this).balance \u003c amount) revert InsufficientEthBalance();\n        (bool success,) = recipient.call{value: amount}(\"\");\n        if (!success) revert EthTransferFailed();\n        emit TipWithdrawalCompleted(recipient, amount);\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue)\n    {\n        return _getMinimumTips(destination, paddedRequest, contentLength).value();\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Sends the given message to the specified destination. Message hash is inserted\n    /// into the Origin Merkle Tree, which will enable message execution on destination chain.\n    function _sendMessage(uint32 destination, uint32 optimisticPeriod, MessageFlag flag, bytes memory body)\n        internal\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // Format the message header\n        messageNonce = _nextNonce();\n        Header header = flag.encodeHeader({\n            origin_: localDomain,\n            nonce_: messageNonce,\n            destination_: destination,\n            optimisticPeriod_: optimisticPeriod\n        });\n        // Format the full message payload\n        bytes memory msgPayload = MessageLib.formatMessage(header, body);\n        // Insert new leaf into the Origin Merkle Tree and save the updated state\n        messageHash = msgPayload.castToMessage().leaf();\n        _insertAndSave(messageHash);\n        // Emit event with message information\n        emit Sent(messageHash, messageNonce, destination, msgPayload);\n        // Update the gas oracle data. We do this after the provided tips are checked so that\n        // the provided message is sent in the event that the gas oracle data is updated to a higher value.\n        InterfaceGasOracle(gasOracle).updateGasData(destination);\n        // TODO: consider doing this before the message is sent, while adjusting GasOracle.getMinimumTips() to\n        // use the pending gas oracle data.\n    }\n\n    /// @dev Returns the minimum tips for sending a message to the given destination with the given request and content.\n    function _getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        internal\n        view\n        returns (Tips)\n    {\n        return\n            TipsLib.wrapPadded(InterfaceGasOracle(gasOracle).getMinimumTips(destination, paddedRequest, contentLength));\n    }\n\n    /// @dev Gets the current gas data from the gas oracle to be saved as part of the Origin State.\n    function _fetchGasData() internal view override returns (GasData) {\n        return GasDataLib.wrapGasData(InterfaceGasOracle(gasOracle).getGasData());\n    }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[],"name":"agentManager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"agent","type":"address"}],"name":"agentStatus","outputs":[{"components":[{"internalType":"enum AgentFlag","name":"flag","type":"uint8"},{"internalType":"uint32","name":"domain","type":"uint32"},{"internalType":"uint32","name":"index","type":"uint32"}],"internalType":"struct AgentStatus","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getAgent","outputs":[{"internalType":"address","name":"agent","type":"address"},{"components":[{"internalType":"enum AgentFlag","name":"flag","type":"uint8"},{"internalType":"uint32","name":"domain","type":"uint32"},{"internalType":"uint32","name":"index","type":"uint32"}],"internalType":"struct AgentStatus","name":"status","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"inbox","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"agentIndex","type":"uint32"}],"name":"latestDisputeStatus","outputs":[{"components":[{"internalType":"enum DisputeFlag","name":"flag","type":"uint8"},{"internalType":"uint40","name":"openedAt","type":"uint40"},{"internalType":"uint40","name":"resolvedAt","type":"uint40"}],"internalType":"struct DisputeStatus","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"guardIndex","type":"uint32"},{"internalType":"uint32","name":"notaryIndex","type":"uint32"}],"name":"openDispute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"slashedIndex","type":"uint32"},{"internalType":"uint32","name":"rivalIndex","type":"uint32"}],"name":"resolveDispute","outputs":[],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{"agentManager()":{"notice":"Returns the address of the local AgentManager contract, which is treated as the \"source of truth\" for agent statuses."},"agentStatus(address)":{"notice":"Returns (flag, domain, index) for a given agent. See Structures.sol for details."},"getAgent(uint256)":{"notice":"Returns agent address and their current status for a given agent index."},"inbox()":{"notice":"Returns the address of the local Inbox contract, which is treated as the \"source of truth\" for agent-signed statements."},"latestDisputeStatus(uint32)":{"notice":"Returns (flag, openedAt, resolvedAt) that describes the latest status of the latest dispute for an agent with a given index."},"openDispute(uint32,uint32)":{"notice":"Local AgentManager should call this function to indicate that a dispute between a Guard and a Notary has been opened."},"resolveDispute(uint32,uint32)":{"notice":"Local AgentManager should call this function to indicate that a dispute has been resolved due to one of the agents being slashed. \u003e `rivalIndex` will be ZERO, if the slashed agent was not in the Dispute."}},"version":1},"developerDoc":{"kind":"dev","methods":{"agentStatus(address)":{"details":"Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud, but their status is not updated to Slashed yet.","params":{"agent":"Agent address"},"returns":{"_0":"Status for the given agent: (flag, domain, index)."}},"getAgent(uint256)":{"details":"Will return empty values if agent with given index doesn't exist.","params":{"index":"Agent index in the Agent Merkle Tree"},"returns":{"agent":"   Agent address","status":"  Status for the given agent: (flag, domain, index)"}},"inbox()":{"details":"Inbox passes verified agent statements to `IAgentSecured` contract."},"latestDisputeStatus(uint32)":{"details":"Will return empty values if agent with given index doesn't exist.","params":{"agentIndex":"Agent index in the Agent Merkle Tree"},"returns":{"_0":"Latest dispute status for the given agent: (flag, openedAt, resolvedAt)"}},"openDispute(uint32,uint32)":{"params":{"guardIndex":"Index of the Guard in the Agent Merkle Tree","notaryIndex":"Index of the Notary in the Agent Merkle Tree"}},"resolveDispute(uint32,uint32)":{"params":{"rivalIndex":"Index of the their Dispute Rival in the Agent Merkle Tree","slashedIndex":"Index of the slashed agent in the Agent Merkle Tree"}}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"agentManager\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"agent\",\"type\":\"address\"}],\"name\":\"agentStatus\",\"outputs\":[{\"components\":[{\"internalType\":\"enum AgentFlag\",\"name\":\"flag\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"domain\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"index\",\"type\":\"uint32\"}],\"internalType\":\"struct AgentStatus\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getAgent\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"agent\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"enum AgentFlag\",\"name\":\"flag\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"domain\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"index\",\"type\":\"uint32\"}],\"internalType\":\"struct AgentStatus\",\"name\":\"status\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"inbox\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"agentIndex\",\"type\":\"uint32\"}],\"name\":\"latestDisputeStatus\",\"outputs\":[{\"components\":[{\"internalType\":\"enum DisputeFlag\",\"name\":\"flag\",\"type\":\"uint8\"},{\"internalType\":\"uint40\",\"name\":\"openedAt\",\"type\":\"uint40\"},{\"internalType\":\"uint40\",\"name\":\"resolvedAt\",\"type\":\"uint40\"}],\"internalType\":\"struct DisputeStatus\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"guardIndex\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"notaryIndex\",\"type\":\"uint32\"}],\"name\":\"openDispute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"slashedIndex\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"rivalIndex\",\"type\":\"uint32\"}],\"name\":\"resolveDispute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"agentStatus(address)\":{\"details\":\"Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud, but their status is not updated to Slashed yet.\",\"params\":{\"agent\":\"Agent address\"},\"returns\":{\"_0\":\"Status for the given agent: (flag, domain, index).\"}},\"getAgent(uint256)\":{\"details\":\"Will return empty values if agent with given index doesn't exist.\",\"params\":{\"index\":\"Agent index in the Agent Merkle Tree\"},\"returns\":{\"agent\":\"   Agent address\",\"status\":\"  Status for the given agent: (flag, domain, index)\"}},\"inbox()\":{\"details\":\"Inbox passes verified agent statements to `IAgentSecured` contract.\"},\"latestDisputeStatus(uint32)\":{\"details\":\"Will return empty values if agent with given index doesn't exist.\",\"params\":{\"agentIndex\":\"Agent index in the Agent Merkle Tree\"},\"returns\":{\"_0\":\"Latest dispute status for the given agent: (flag, openedAt, resolvedAt)\"}},\"openDispute(uint32,uint32)\":{\"params\":{\"guardIndex\":\"Index of the Guard in the Agent Merkle Tree\",\"notaryIndex\":\"Index of the Notary in the Agent Merkle Tree\"}},\"resolveDispute(uint32,uint32)\":{\"params\":{\"rivalIndex\":\"Index of the their Dispute Rival in the Agent Merkle Tree\",\"slashedIndex\":\"Index of the slashed agent in the Agent Merkle Tree\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"agentManager()\":{\"notice\":\"Returns the address of the local AgentManager contract, which is treated as the \\\"source of truth\\\" for agent statuses.\"},\"agentStatus(address)\":{\"notice\":\"Returns (flag, domain, index) for a given agent. See Structures.sol for details.\"},\"getAgent(uint256)\":{\"notice\":\"Returns agent address and their current status for a given agent index.\"},\"inbox()\":{\"notice\":\"Returns the address of the local Inbox contract, which is treated as the \\\"source of truth\\\" for agent-signed statements.\"},\"latestDisputeStatus(uint32)\":{\"notice\":\"Returns (flag, openedAt, resolvedAt) that describes the latest status of the latest dispute for an agent with a given index.\"},\"openDispute(uint32,uint32)\":{\"notice\":\"Local AgentManager should call this function to indicate that a dispute between a Guard and a Notary has been opened.\"},\"resolveDispute(uint32,uint32)\":{\"notice\":\"Local AgentManager should call this function to indicate that a dispute has been resolved due to one of the agents being slashed. \u003e `rivalIndex` will be ZERO, if the slashed agent was not in the Dispute.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Origin.sol\":\"IAgentSecured\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Origin.sol\":{\"keccak256\":\"0x96775924f147f3d1f8df8cdf56731fe52a15af8d8e12e608efb8158c112b18cd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e642a27f5fab3c62b4c02e9754e9e42b1cf2e5381dbea9d3d106d23b7772ebe6\",\"dweb:/ipfs/QmUwn7ZyBvPkjnMuK8ZMSexBUdNQnVtxwyoAyT4DXLQjra\"]}},\"version\":1}"},"hashes":{"agentManager()":"7622f78d","agentStatus(address)":"28f3fac9","getAgent(uint256)":"2de5aaf7","inbox()":"fb0e722b","latestDisputeStatus(uint32)":"dfadd81a","openDispute(uint32,uint32)":"a2155c34","resolveDispute(uint32,uint32)":"61169218"}},"solidity/Origin.sol:IStateHub":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/OriginEvents.sol\n\n/// @notice A collection of events emitted by the Origin contract\nabstract contract OriginEvents {\n    /**\n     * @notice Emitted when a new message is sent.\n     * @param messageHash   Hash of message; the leaf inserted to the Merkle tree for the message\n     * @param nonce         Nonce of sent message (starts from 1)\n     * @param destination   Destination domain\n     * @param message       Raw bytes of message\n     */\n    event Sent(bytes32 indexed messageHash, uint32 indexed nonce, uint32 indexed destination, bytes message);\n\n    /**\n     * @notice Emitted when a tip withdrawal is completed.\n     * @param actor     Actor address\n     * @param tip       Tip value, denominated in local domain's wei\n     */\n    event TipWithdrawalCompleted(address actor, uint256 tip);\n}\n\n// contracts/events/StateHubEvents.sol\n\n/// @notice A collection of events emitted by the StateHub contract\nabstract contract StateHubEvents {\n    /**\n     * @notice Emitted when a new Origin State is saved after a message was sent.\n     * @param state     Raw payload with state data\n     */\n    event StateSaved(bytes state);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n    /**\n     * @notice Check that a given state is valid: matches the historical state of Origin contract.\n     * Note: any Agent including an invalid state in their snapshot will be slashed\n     * upon providing the snapshot and agent signature for it to Origin contract.\n     * @dev Will revert if any of these is true:\n     *  - State payload is not properly formatted.\n     * @param statePayload      Raw payload with state data\n     * @return isValid          Whether the provided state is valid\n     */\n    function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns the amount of saved states so far.\n     * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n     */\n    function statesAmount() external view returns (uint256);\n\n    /**\n     * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @return statePayload     Raw payload with the latest state data\n     */\n    function suggestLatestState() external view returns (bytes memory statePayload);\n\n    /**\n     * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @param nonce             Historical nonce to form a state\n     * @return statePayload     Raw payload with historical state data\n     */\n    function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/InterfaceGasOracle.sol\n\ninterface InterfaceGasOracle {\n    /**\n     * @notice Fetches the latest gas data for the chain from `Destination` contract,\n     * and uses it to update the oracle values for the requested chain.\n     * @param domain    Domain to update the gas data for\n     */\n    function updateGasData(uint32 domain) external;\n\n    /**\n     * @notice Returns the gas data for the local chain.\n     */\n    function getGasData() external view returns (uint256 paddedGasData);\n\n    /**\n     * @notice Returns the gas data for the given domain, in the decoded format.\n     * @param domain        Domain of chain to get gas data for\n     * @return gasPrice     Gas price for the chain (in Wei per gas unit)\n     * @return dataPrice    Calldata price (in Wei per byte of content)\n     * @return execBuffer   Tx fee safety buffer for message execution (in Wei)\n     * @return amortAttCost Amortized cost for attestation submission (in Wei)\n     * @return etherPrice   Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n     * @return markup       Markup for the message execution (in BWAD)\n     */\n    function getDecodedGasData(uint32 domain)\n        external\n        view\n        returns (\n            uint256 gasPrice,\n            uint256 dataPrice,\n            uint256 execBuffer,\n            uint256 amortAttCost,\n            uint256 etherPrice,\n            uint256 markup\n        );\n\n    /**\n     * @notice Returns the minimum tips for sending a message to a given destination.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return paddedTips       Padded encoded minimum tips information\n     */\n    function getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 paddedTips);\n}\n\n// contracts/interfaces/InterfaceOrigin.sol\n\ninterface InterfaceOrigin {\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /**\n     * @notice Send a message to the recipient located on destination domain.\n     * @dev Recipient has to conform to IMessageRecipient interface, otherwise message won't be delivered.\n     * Will revert if any of these is true:\n     * - `destination` is equal to contract's local domain\n     * - `content` length is greater than `MAX_CONTENT_BYTES`\n     * - `msg.value` is lower than value of minimum tips for the given message\n     * @param destination           Domain of destination chain\n     * @param recipient             Address of recipient on destination chain as bytes32\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param paddedRequest         Padded encoded message execution request on destination chain\n     * @param content               Raw bytes content of message\n     * @return messageNonce         Nonce of the sent message\n     * @return messageHash          Hash of the sent message\n     */\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable returns (uint32 messageNonce, bytes32 messageHash);\n\n    /**\n     * @notice Send a manager message to the destination domain.\n     * @dev This could only be called by AgentManager, which takes care of encoding the calldata payload.\n     * Note: (msgOrigin, proofMaturity) security args will be added to payload on the destination chain\n     * so that the AgentManager could verify where the Manager Message came from and how mature is the proof.\n     * Note: function is not payable, as no tips are required for sending a manager message.\n     * Will revert if `destination` is equal to contract's local domain.\n     * @param destination           Domain of destination chain\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param payload               Payload for calling AgentManager on destination chain (with extra security args)\n     */\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        returns (uint32 messageNonce, bytes32 messageHash);\n\n    // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Withdraws locked base message tips to the recipient.\n     * @dev Could only be called by a local AgentManager.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function withdrawTips(address recipient, uint256 amount) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the minimum tips value for sending a message to a given destination.\n     * @dev Using at least `tipsValue` as `msg.value` for `sendBaseMessage()`\n     * will guarantee that the message will be accepted.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return tipsValue        Minimum tips value for a message to be accepted\n     */\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue);\n}\n\n// contracts/libs/Constants.sol\n\n// Here we define common constants to enable their easier reusing later.\n\n// ══════════════════════════════════ MERKLE ═══════════════════════════════════\n/// @dev Height of the Agent Merkle Tree\nuint256 constant AGENT_TREE_HEIGHT = 32;\n/// @dev Height of the Origin Merkle Tree\nuint256 constant ORIGIN_TREE_HEIGHT = 32;\n/// @dev Height of the Snapshot Merkle Tree. Allows up to 64 leafs, e.g. up to 32 states\nuint256 constant SNAPSHOT_TREE_HEIGHT = 6;\n// ══════════════════════════════════ STRUCTS ══════════════════════════════════\n/// @dev See Attestation.sol: (bytes32,bytes32,uint32,uint40,uint40): 32+32+4+5+5\nuint256 constant ATTESTATION_LENGTH = 78;\n/// @dev See GasData.sol: (uint16,uint16,uint16,uint16,uint16,uint16): 2+2+2+2+2+2\nuint256 constant GAS_DATA_LENGTH = 12;\n/// @dev See Receipt.sol: (uint32,uint32,bytes32,bytes32,uint8,address,address,address): 4+4+32+32+1+20+20+20\nuint256 constant RECEIPT_LENGTH = 133;\n/// @dev See State.sol: (bytes32,uint32,uint32,uint40,uint40,GasData): 32+4+4+5+5+len(GasData)\nuint256 constant STATE_LENGTH = 50 + GAS_DATA_LENGTH;\n/// @dev Maximum amount of states in a single snapshot. Each state produces two leafs in the tree\nuint256 constant SNAPSHOT_MAX_STATES = 1 \u003c\u003c (SNAPSHOT_TREE_HEIGHT - 1);\n// ══════════════════════════════════ MESSAGE ══════════════════════════════════\n/// @dev See Header.sol: (uint8,uint32,uint32,uint32,uint32): 1+4+4+4+4\nuint256 constant HEADER_LENGTH = 17;\n/// @dev See Request.sol: (uint96,uint64,uint32): 12+8+4\nuint256 constant REQUEST_LENGTH = 24;\n/// @dev See Tips.sol: (uint64,uint64,uint64,uint64): 8+8+8+8\nuint256 constant TIPS_LENGTH = 32;\n/// @dev The amount of discarded last bits when encoding tip values\nuint256 constant TIPS_GRANULARITY = 32;\n/// @dev Tip values could be only the multiples of TIPS_MULTIPLIER\nuint256 constant TIPS_MULTIPLIER = 1 \u003c\u003c TIPS_GRANULARITY;\n// ══════════════════════════════ STATEMENT SALTS ══════════════════════════════\n/// @dev Salts for signing various statements\nbytes32 constant ATTESTATION_VALID_SALT = keccak256(\"ATTESTATION_VALID_SALT\");\nbytes32 constant ATTESTATION_INVALID_SALT = keccak256(\"ATTESTATION_INVALID_SALT\");\nbytes32 constant RECEIPT_VALID_SALT = keccak256(\"RECEIPT_VALID_SALT\");\nbytes32 constant RECEIPT_INVALID_SALT = keccak256(\"RECEIPT_INVALID_SALT\");\nbytes32 constant SNAPSHOT_VALID_SALT = keccak256(\"SNAPSHOT_VALID_SALT\");\nbytes32 constant STATE_INVALID_SALT = keccak256(\"STATE_INVALID_SALT\");\n// ═════════════════════════════════ PROTOCOL ══════════════════════════════════\n/// @dev Optimistic period for new agent roots in LightManager\nuint32 constant AGENT_ROOT_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Timeout between the agent root could be proposed and resolved in LightManager\nuint32 constant AGENT_ROOT_PROPOSAL_TIMEOUT = 12 hours;\nuint32 constant BONDING_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Amount of time that the Notary will not be considered active after they won a dispute\nuint32 constant DISPUTE_TIMEOUT_NOTARY = 12 hours;\n/// @dev Amount of time without fresh data from Notaries before contract owner can resolve stuck disputes manually\nuint256 constant FRESH_DATA_TIMEOUT = 4 hours;\n/// @dev Maximum bytes per message = 2 KiB (somewhat arbitrarily set to begin)\nuint256 constant MAX_CONTENT_BYTES = 2 * 2 ** 10;\n/// @dev Maximum value for the summit tip that could be set in GasOracle\nuint256 constant MAX_SUMMIT_TIP = 0.01 ether;\n\n// contracts/libs/Errors.sol\n\n// ══════════════════════════════ INVALID CALLER ═══════════════════════════════\n\nerror CallerNotAgentManager();\nerror CallerNotDestination();\nerror CallerNotInbox();\nerror CallerNotSummit();\n\n// ══════════════════════════════ INCORRECT DATA ═══════════════════════════════\n\nerror IncorrectAttestation();\nerror IncorrectAgentDomain();\nerror IncorrectAgentIndex();\nerror IncorrectAgentProof();\nerror IncorrectAgentRoot();\nerror IncorrectDataHash();\nerror IncorrectDestinationDomain();\nerror IncorrectOriginDomain();\nerror IncorrectSnapshotProof();\nerror IncorrectSnapshotRoot();\nerror IncorrectState();\nerror IncorrectStatesAmount();\nerror IncorrectTipsProof();\nerror IncorrectVersionLength();\n\nerror IncorrectNonce();\nerror IncorrectSender();\nerror IncorrectRecipient();\n\nerror FlagOutOfRange();\nerror IndexOutOfRange();\nerror NonceOutOfRange();\n\nerror OutdatedNonce();\n\nerror UnformattedAttestation();\nerror UnformattedAttestationReport();\nerror UnformattedBaseMessage();\nerror UnformattedCallData();\nerror UnformattedCallDataPrefix();\nerror UnformattedMessage();\nerror UnformattedReceipt();\nerror UnformattedReceiptReport();\nerror UnformattedSignature();\nerror UnformattedSnapshot();\nerror UnformattedState();\nerror UnformattedStateReport();\n\n// ═══════════════════════════════ MERKLE TREES ════════════════════════════════\n\nerror LeafNotProven();\nerror MerkleTreeFull();\nerror NotEnoughLeafs();\nerror TreeHeightTooLow();\n\n// ═════════════════════════════ OPTIMISTIC PERIOD ═════════════════════════════\n\nerror BaseClientOptimisticPeriod();\nerror MessageOptimisticPeriod();\nerror SlashAgentOptimisticPeriod();\nerror WithdrawTipsOptimisticPeriod();\nerror ZeroProofMaturity();\n\n// ═══════════════════════════════ AGENT MANAGER ═══════════════════════════════\n\nerror AgentNotGuard();\nerror AgentNotNotary();\n\nerror AgentCantBeAdded();\nerror AgentNotActive();\nerror AgentNotActiveNorUnstaking();\nerror AgentNotFraudulent();\nerror AgentNotUnstaking();\nerror AgentUnknown();\n\nerror AgentRootNotProposed();\nerror AgentRootTimeoutNotOver();\n\nerror NotStuck();\n\nerror DisputeAlreadyResolved();\nerror DisputeNotOpened();\nerror DisputeTimeoutNotOver();\nerror GuardInDispute();\nerror NotaryInDispute();\n\nerror MustBeSynapseDomain();\nerror SynapseDomainForbidden();\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\nerror AlreadyExecuted();\nerror AlreadyFailed();\nerror DuplicatedSnapshotRoot();\nerror IncorrectMagicValue();\nerror GasLimitTooLow();\nerror GasSuppliedTooLow();\n\n// ══════════════════════════════════ ORIGIN ═══════════════════════════════════\n\nerror ContentLengthTooBig();\nerror EthTransferFailed();\nerror InsufficientEthBalance();\n\n// ════════════════════════════════ GAS ORACLE ═════════════════════════════════\n\nerror LocalGasDataNotSet();\nerror RemoteGasDataNotSet();\n\n// ═══════════════════════════════════ TIPS ════════════════════════════════════\n\nerror SummitTipTooHigh();\nerror TipsClaimMoreThanEarned();\nerror TipsClaimZero();\nerror TipsOverflow();\nerror TipsValueTooLow();\n\n// ════════════════════════════════ MEMORY VIEW ════════════════════════════════\n\nerror IndexedTooMuch();\nerror ViewOverrun();\nerror OccupiedMemory();\nerror UnallocatedMemory();\nerror PrecompileOutOfGas();\n\n// ═════════════════════════════════ MULTICALL ═════════════════════════════════\n\nerror MulticallFailed();\n\n// contracts/libs/TypeCasts.sol\n\nlibrary TypeCasts {\n    // alignment preserving cast\n    function addressToBytes32(address addr) internal pure returns (bytes32) {\n        return bytes32(uint256(uint160(addr)));\n    }\n\n    // alignment preserving cast\n    function bytes32ToAddress(bytes32 buf) internal pure returns (address) {\n        return address(uint160(uint256(buf)));\n    }\n}\n\n// contracts/libs/stack/Number.sol\n\n/// Number is a compact representation of uint256, that is fit into 16 bits\n/// with the maximum relative error under 0.4%.\ntype Number is uint16;\n\nusing NumberLib for Number global;\n\n/// # Number\n/// Library for compact representation of uint256 numbers.\n/// - Number is stored using mantissa and exponent, each occupying 8 bits.\n/// - Numbers under 2**8 are stored as `mantissa` with `exponent = 0xFF`.\n/// - Numbers at least 2**8 are approximated as `(256 + mantissa) \u003c\u003c exponent`\n/// \u003e - `0 \u003c= mantissa \u003c 256`\n/// \u003e - `0 \u003c= exponent \u003c= 247` (`256 * 2**248` doesn't fit into uint256)\n/// # Number stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type  | Bytes |\n/// | ---------- | -------- | ----- | ----- |\n/// | (002..001] | mantissa | uint8 | 1     |\n/// | (001..000] | exponent | uint8 | 1     |\n\nlibrary NumberLib {\n    /// @dev Amount of bits to shift to mantissa field\n    uint16 private constant SHIFT_MANTISSA = 8;\n\n    /// @notice For bwad math (binary wad) we use 2**64 as \"wad\" unit.\n    /// @dev We are using not using 10**18 as wad, because it is not stored precisely in NumberLib.\n    uint256 internal constant BWAD_SHIFT = 64;\n    uint256 internal constant BWAD = 1 \u003c\u003c BWAD_SHIFT;\n    /// @notice ~0.1% in bwad units.\n    uint256 internal constant PER_MILLE_SHIFT = BWAD_SHIFT - 10;\n    uint256 internal constant PER_MILLE = 1 \u003c\u003c PER_MILLE_SHIFT;\n\n    /// @notice Compresses uint256 number into 16 bits.\n    function compress(uint256 value) internal pure returns (Number) {\n        // Find `msb` such as `2**msb \u003c= value \u003c 2**(msb + 1)`\n        uint256 msb = mostSignificantBit(value);\n        // We want to preserve 9 bits of precision.\n        // The highest bit is always 1, so we can skip it.\n        // The remaining 8 highest bits are stored as mantissa.\n        if (msb \u003c 8) {\n            // Value is less than 2**8, so we can use value as mantissa with \"-1\" exponent.\n            return _encode(uint8(value), 0xFF);\n        } else {\n            // We use `msb - 8` as exponent otherwise. Note that `exponent \u003e= 0`.\n            unchecked {\n                uint256 exponent = msb - 8;\n                // Shifting right by `msb-8` bits will shift the \"remaining 8 highest bits\" into the 8 lowest bits.\n                // uint8() will truncate the highest bit.\n                return _encode(uint8(value \u003e\u003e exponent), uint8(exponent));\n            }\n        }\n    }\n\n    /// @notice Decompresses 16 bits number into uint256.\n    /// @dev The outcome is an approximation of the original number: `(value - value / 256) \u003c number \u003c= value`.\n    function decompress(Number number) internal pure returns (uint256 value) {\n        // Isolate 8 highest bits as the mantissa.\n        uint256 mantissa = Number.unwrap(number) \u003e\u003e SHIFT_MANTISSA;\n        // This will truncate the highest bits, leaving only the exponent.\n        uint256 exponent = uint8(Number.unwrap(number));\n        if (exponent == 0xFF) {\n            return mantissa;\n        } else {\n            unchecked {\n                return (256 + mantissa) \u003c\u003c (exponent);\n            }\n        }\n    }\n\n    /// @dev Returns the most significant bit of `x`\n    /// https://solidity-by-example.org/bitwise/\n    function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\n        // To find `msb` we determine it bit by bit, starting from the highest one.\n        // `0 \u003c= msb \u003c= 255`, so we start from the highest bit, 1\u003c\u003c7 == 128.\n        // If `x` is at least 2**128, then the highest bit of `x` is at least 128.\n        // solhint-disable no-inline-assembly\n        assembly {\n            // `f` is set to 1\u003c\u003c7 if `x \u003e= 2**128` and to 0 otherwise.\n            let f := shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\n            // If `x \u003e= 2**128` then set `msb` highest bit to 1 and shift `x` right by 128.\n            // Otherwise, `msb` remains 0 and `x` remains unchanged.\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        // `x` is now at most 2**128 - 1. Continue the same way, the next highest bit is 1\u003c\u003c6 == 64.\n        assembly {\n            // `f` is set to 1\u003c\u003c6 if `x \u003e= 2**64` and to 0 otherwise.\n            let f := shl(6, gt(x, 0xFFFFFFFFFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c5 if `x \u003e= 2**32` and to 0 otherwise.\n            let f := shl(5, gt(x, 0xFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c4 if `x \u003e= 2**16` and to 0 otherwise.\n            let f := shl(4, gt(x, 0xFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c3 if `x \u003e= 2**8` and to 0 otherwise.\n            let f := shl(3, gt(x, 0xFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c2 if `x \u003e= 2**4` and to 0 otherwise.\n            let f := shl(2, gt(x, 0xF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c1 if `x \u003e= 2**2` and to 0 otherwise.\n            let f := shl(1, gt(x, 0x3))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1 if `x \u003e= 2**1` and to 0 otherwise.\n            let f := gt(x, 0x1)\n            msb := or(msb, f)\n        }\n    }\n\n    /// @dev Wraps (mantissa, exponent) pair into Number.\n    function _encode(uint8 mantissa, uint8 exponent) private pure returns (Number) {\n        // Casts below are upcasts, so they are safe.\n        return Number.wrap(uint16(mantissa) \u003c\u003c SHIFT_MANTISSA | uint16(exponent));\n    }\n}\n\n// contracts/libs/stack/Request.sol\n\n/// Request is encoded data with \"message execution request\".\ntype Request is uint192;\n\nusing RequestLib for Request global;\n\n/// Library for formatting _the request part_ of _the base messages_.\n/// - Request represents a message sender requirements for the message execution on the destination chain.\n/// - Request occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n/// \u003e gasDrop field is included for future compatibility and is ignored at the moment.\n///\n/// # Request stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type   | Bytes | Description                                          |\n/// | ---------- | -------- | ------ | ----- | ---------------------------------------------------- |\n/// | (024..012] | gasDrop  | uint96 | 12    | Minimum amount of gas token to drop to the recipient |\n/// | (012..004] | gasLimit | uint64 | 8     | Minimum amount of gas units to supply for execution  |\n/// | (004..000] | version  | uint32 | 4     | Base message version to pass to the recipient        |\n\nlibrary RequestLib {\n    /// @dev Amount of bits to shift to gasDrop field\n    uint192 private constant SHIFT_GAS_DROP = 12 * 8;\n    /// @dev Amount of bits to shift to gasLimit field\n    uint192 private constant SHIFT_GAS_LIMIT = 4 * 8;\n\n    /// @notice Returns an encoded request with the given fields\n    /// @param gasDrop_     Minimum amount of gas token to drop to the recipient (ignored at the moment)\n    /// @param gasLimit_    Minimum amount of gas units to supply for execution\n    /// @param version_     Base message version to pass to the recipient\n    function encodeRequest(uint96 gasDrop_, uint64 gasLimit_, uint32 version_) internal pure returns (Request) {\n        // Casts below are upcasts, so they are safe\n        return Request.wrap(uint192(gasDrop_) \u003c\u003c SHIFT_GAS_DROP | uint192(gasLimit_) \u003c\u003c SHIFT_GAS_LIMIT | version_);\n    }\n\n    /// @notice Wraps the padded encoded request into a Request-typed value.\n    /// @dev The \"padded\" request is simply an encoded request casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded requests\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedRequest) internal pure returns (Request) {\n        // Casting to uint192 will truncate the highest bits, which is the behavior we want\n        return Request.wrap(uint192(paddedRequest));\n    }\n\n    /// @notice Returns the requested of gas token to drop to the recipient.\n    function gasDrop(Request request) internal pure returns (uint96) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return uint96(Request.unwrap(request) \u003e\u003e SHIFT_GAS_DROP);\n    }\n\n    /// @notice Returns the requested minimum amount of gas units to supply for execution.\n    function gasLimit(Request request) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Request.unwrap(request) \u003e\u003e SHIFT_GAS_LIMIT);\n    }\n\n    /// @notice Returns the requested base message version to pass to the recipient.\n    function version(Request request) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Request.unwrap(request));\n    }\n}\n\n// node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        require(value \u003c= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        require(value \u003c= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        require(value \u003c= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value \u003c= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        require(value \u003c= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        require(value \u003c= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        require(value \u003c= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        require(value \u003c= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        require(value \u003c= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        require(value \u003c= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        require(value \u003c= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        require(value \u003c= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        require(value \u003c= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        require(value \u003c= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        require(value \u003c= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value \u003c= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        require(value \u003c= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        require(value \u003c= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        require(value \u003c= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value \u003c= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        require(value \u003c= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        require(value \u003c= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        require(value \u003c= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value \u003c= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        require(value \u003c= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        require(value \u003c= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        require(value \u003c= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value \u003c= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        require(value \u003c= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value \u003c= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value \u003c= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     *\n     * _Available since v3.0._\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value \u003e= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     *\n     * _Available since v3.0._\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value \u003c= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     *\n     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length \u003e 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance \u003e= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance \u003e= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length \u003e 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n\n// contracts/base/MultiCallable.sol\n\n/// @notice Collection of Multicall utilities. Fork of Multicall3:\n/// https://github.com/mds1/multicall/blob/master/src/Multicall3.sol\nabstract contract MultiCallable {\n    struct Call {\n        bool allowFailure;\n        bytes callData;\n    }\n\n    struct Result {\n        bool success;\n        bytes returnData;\n    }\n\n    /// @notice Aggregates a few calls to this contract into one multicall without modifying `msg.sender`.\n    function multicall(Call[] calldata calls) external returns (Result[] memory callResults) {\n        uint256 amount = calls.length;\n        callResults = new Result[](amount);\n        Call calldata call_;\n        for (uint256 i = 0; i \u003c amount;) {\n            call_ = calls[i];\n            Result memory result = callResults[i];\n            // We perform a delegate call to ourselves here. Delegate call does not modify `msg.sender`, so\n            // this will have the same effect as if `msg.sender` performed all the calls themselves one by one.\n            // solhint-disable-next-line avoid-low-level-calls\n            (result.success, result.returnData) = address(this).delegatecall(call_.callData);\n            // solhint-disable-next-line no-inline-assembly\n            assembly {\n                // Revert if the call fails and failure is not allowed\n                // `allowFailure := calldataload(call_)` and `success := mload(result)`\n                if iszero(or(calldataload(call_), mload(result))) {\n                    // Revert with `0x4d6a2328` (function selector for `MulticallFailed()`)\n                    mstore(0x00, 0x4d6a232800000000000000000000000000000000000000000000000000000000)\n                    revert(0x00, 0x04)\n                }\n            }\n            unchecked {\n                ++i;\n            }\n        }\n    }\n}\n\n// contracts/base/Version.sol\n\n/**\n * @title Versioned\n * @notice Version getter for contracts. Doesn't use any storage slots, meaning\n * it will never cause any troubles with the upgradeable contracts. For instance, this contract\n * can be added or removed from the inheritance chain without shifting the storage layout.\n */\nabstract contract Versioned {\n    /**\n     * @notice Struct that is mimicking the storage layout of a string with 32 bytes or less.\n     * Length is limited by 32, so the whole string payload takes two memory words:\n     * @param length    String length\n     * @param data      String characters\n     */\n    struct _ShortString {\n        uint256 length;\n        bytes32 data;\n    }\n\n    /// @dev Length of the \"version string\"\n    uint256 private immutable _length;\n    /// @dev Bytes representation of the \"version string\".\n    /// Strings with length over 32 are not supported!\n    bytes32 private immutable _data;\n\n    constructor(string memory version_) {\n        _length = bytes(version_).length;\n        if (_length \u003e 32) revert IncorrectVersionLength();\n        // bytes32 is left-aligned =\u003e this will store the byte representation of the string\n        // with the trailing zeroes to complete the 32-byte word\n        _data = bytes32(bytes(version_));\n    }\n\n    function version() external view returns (string memory versionString) {\n        // Load the immutable values to form the version string\n        _ShortString memory str = _ShortString(_length, _data);\n        // The only way to do this cast is doing some dirty assembly\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            versionString := str\n        }\n    }\n}\n\n// contracts/libs/ChainContext.sol\n\n/// @notice Library for accessing chain context variables as tightly packed integers.\n/// Messaging contracts should rely on this library for accessing chain context variables\n/// instead of doing the casting themselves.\nlibrary ChainContext {\n    using SafeCast for uint256;\n\n    /// @notice Returns the current block number as uint40.\n    /// @dev Reverts if block number is greater than 40 bits, which is not supposed to happen\n    /// until the block.timestamp overflows (assuming block time is at least 1 second).\n    function blockNumber() internal view returns (uint40) {\n        return block.number.toUint40();\n    }\n\n    /// @notice Returns the current block timestamp as uint40.\n    /// @dev Reverts if block timestamp is greater than 40 bits, which is\n    /// supposed to happen approximately in year 36835.\n    function blockTimestamp() internal view returns (uint40) {\n        return block.timestamp.toUint40();\n    }\n\n    /// @notice Returns the chain id as uint32.\n    /// @dev Reverts if chain id is greater than 32 bits, which is not\n    /// supposed to happen in production.\n    function chainId() internal view returns (uint32) {\n        return block.chainid.toUint32();\n    }\n}\n\n// contracts/libs/Structures.sol\n\n// Here we define common enums and structures to enable their easier reusing later.\n\n// ═══════════════════════════════ AGENT STATUS ════════════════════════════════\n\n/// @dev Potential statuses for the off-chain bonded agent:\n/// - Unknown: never provided a bond =\u003e signature not valid\n/// - Active: has a bond in BondingManager =\u003e signature valid\n/// - Unstaking: has a bond in BondingManager, initiated the unstaking =\u003e signature not valid\n/// - Resting: used to have a bond in BondingManager, successfully unstaked =\u003e signature not valid\n/// - Fraudulent: proven to commit fraud, value in Merkle Tree not updated =\u003e signature not valid\n/// - Slashed: proven to commit fraud, value in Merkle Tree was updated =\u003e signature not valid\n/// Unstaked agent could later be added back to THE SAME domain by staking a bond again.\n/// Honest agent: Unknown -\u003e Active -\u003e unstaking -\u003e Resting -\u003e Active ...\n/// Malicious agent: Unknown -\u003e Active -\u003e Fraudulent -\u003e Slashed\n/// Malicious agent: Unknown -\u003e Active -\u003e Unstaking -\u003e Fraudulent -\u003e Slashed\nenum AgentFlag {\n    Unknown,\n    Active,\n    Unstaking,\n    Resting,\n    Fraudulent,\n    Slashed\n}\n\n/// @notice Struct for storing an agent in the BondingManager contract.\nstruct AgentStatus {\n    AgentFlag flag;\n    uint32 domain;\n    uint32 index;\n}\n// 184 bits available for tight packing\n\nusing StructureUtils for AgentStatus global;\n\n/// @notice Potential statuses of an agent in terms of being in dispute\n/// - None: agent is not in dispute\n/// - Pending: agent is in unresolved dispute\n/// - Slashed: agent was in dispute that lead to agent being slashed\n/// Note: agent who won the dispute has their status reset to None\nenum DisputeFlag {\n    None,\n    Pending,\n    Slashed\n}\n\n/// @notice Struct for storing dispute status of an agent.\n/// @param flag         Dispute flag: None/Pending/Slashed.\n/// @param openedAt     Timestamp when the latest agent dispute was opened (zero if not opened).\n/// @param resolvedAt   Timestamp when the latest agent dispute was resolved (zero if not resolved).\nstruct DisputeStatus {\n    DisputeFlag flag;\n    uint40 openedAt;\n    uint40 resolvedAt;\n}\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\n/// @notice Struct representing the status of Destination contract.\n/// @param snapRootTime     Timestamp when latest snapshot root was accepted\n/// @param agentRootTime    Timestamp when latest agent root was accepted\n/// @param notaryIndex      Index of Notary who signed the latest agent root\nstruct DestinationStatus {\n    uint40 snapRootTime;\n    uint40 agentRootTime;\n    uint32 notaryIndex;\n}\n\n// ═══════════════════════════════ EXECUTION HUB ═══════════════════════════════\n\n/// @notice Potential statuses of the message in Execution Hub.\n/// - None: there hasn't been a valid attempt to execute the message yet\n/// - Failed: there was a valid attempt to execute the message, but recipient reverted\n/// - Success: there was a valid attempt to execute the message, and recipient did not revert\n/// Note: message can be executed until its status is Success\nenum MessageStatus {\n    None,\n    Failed,\n    Success\n}\n\nlibrary StructureUtils {\n    /// @notice Checks that Agent is Active\n    function verifyActive(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active) {\n            revert AgentNotActive();\n        }\n    }\n\n    /// @notice Checks that Agent is Unstaking\n    function verifyUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Unstaking) {\n            revert AgentNotUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Active or Unstaking\n    function verifyActiveUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active \u0026\u0026 status.flag != AgentFlag.Unstaking) {\n            revert AgentNotActiveNorUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Fraudulent\n    function verifyFraudulent(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Fraudulent) {\n            revert AgentNotFraudulent();\n        }\n    }\n\n    /// @notice Checks that Agent is not Unknown\n    function verifyKnown(AgentStatus memory status) internal pure {\n        if (status.flag == AgentFlag.Unknown) {\n            revert AgentUnknown();\n        }\n    }\n}\n\n// contracts/libs/memory/MemView.sol\n\n/// @dev MemView is an untyped view over a portion of memory to be used instead of `bytes memory`\ntype MemView is uint256;\n\n/// @dev Attach library functions to MemView\nusing MemViewLib for MemView global;\n\n/// @notice Library for operations with the memory views.\n/// Forked from https://github.com/summa-tx/memview-sol with several breaking changes:\n/// - The codebase is ported to Solidity 0.8\n/// - Custom errors are added\n/// - The runtime type checking is replaced with compile-time check provided by User-Defined Value Types\n///   https://docs.soliditylang.org/en/latest/types.html#user-defined-value-types\n/// - uint256 is used as the underlying type for the \"memory view\" instead of bytes29.\n///   It is wrapped into MemView custom type in order not to be confused with actual integers.\n/// - Therefore the \"type\" field is discarded, allowing to allocate 16 bytes for both view location and length\n/// - The documentation is expanded\n/// - Library functions unused by the rest of the codebase are removed\n//  - Very pretty code separators are added :)\nlibrary MemViewLib {\n    /// @notice Stack layout for uint256 (from highest bits to lowest)\n    /// (32 .. 16]      loc     16 bytes    Memory address of underlying bytes\n    /// (16 .. 00]      len     16 bytes    Length of underlying bytes\n\n    // ═══════════════════════════════════════════ BUILDING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Instantiate a new untyped memory view. This should generally not be called directly.\n     * Prefer `ref` wherever possible.\n     * @param loc_          The memory address\n     * @param len_          The length\n     * @return The new view with the specified location and length\n     */\n    function build(uint256 loc_, uint256 len_) internal pure returns (MemView) {\n        uint256 end_ = loc_ + len_;\n        // Make sure that a view is not constructed that points to unallocated memory\n        // as this could be indicative of a buffer overflow attack\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            if gt(end_, mload(0x40)) { end_ := 0 }\n        }\n        if (end_ == 0) {\n            revert UnallocatedMemory();\n        }\n        return _unsafeBuildUnchecked(loc_, len_);\n    }\n\n    /**\n     * @notice Instantiate a memory view from a byte array.\n     * @dev Note that due to Solidity memory representation, it is not possible to\n     * implement a deref, as the `bytes` type stores its len in memory.\n     * @param arr           The byte array\n     * @return The memory view over the provided byte array\n     */\n    function ref(bytes memory arr) internal pure returns (MemView) {\n        uint256 len_ = arr.length;\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 loc_;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // We add 0x20, so that the view starts exactly where the array data starts\n            loc_ := add(arr, 0x20)\n        }\n        return build(loc_, len_);\n    }\n\n    // ════════════════════════════════════════════ CLONING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to the new memory.\n     * @param memView       The memory view\n     * @return arr          The cloned byte array\n     */\n    function clone(MemView memView) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        unchecked {\n            _unsafeCopyTo(memView, ptr + 0x20);\n        }\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 len_ = memView.len();\n        uint256 footprint_ = memView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    /**\n     * @notice Copies all views, joins them into a new bytearray.\n     * @param memViews      The memory views\n     * @return arr          The new byte array with joined data behind the given views\n     */\n    function join(MemView[] memory memViews) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        MemView newView;\n        unchecked {\n            newView = _unsafeJoin(memViews, ptr + 0x20);\n        }\n        uint256 len_ = newView.len();\n        uint256 footprint_ = newView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    // ══════════════════════════════════════════ INSPECTING MEMORY VIEW ═══════════════════════════════════════════════\n\n    /**\n     * @notice Returns the memory address of the underlying bytes.\n     * @param memView       The memory view\n     * @return loc_         The memory address\n     */\n    function loc(MemView memView) internal pure returns (uint256 loc_) {\n        // loc is stored in the highest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u003e\u003e 128;\n    }\n\n    /**\n     * @notice Returns the number of bytes of the view.\n     * @param memView       The memory view\n     * @return len_         The length of the view\n     */\n    function len(MemView memView) internal pure returns (uint256 len_) {\n        // len is stored in the lowest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u0026 type(uint128).max;\n    }\n\n    /**\n     * @notice Returns the endpoint of `memView`.\n     * @param memView       The memory view\n     * @return end_         The endpoint of `memView`\n     */\n    function end(MemView memView) internal pure returns (uint256 end_) {\n        // The endpoint never overflows uint128, let alone uint256, so we could use unchecked math here\n        unchecked {\n            return memView.loc() + memView.len();\n        }\n    }\n\n    /**\n     * @notice Returns the number of memory words this memory view occupies, rounded up.\n     * @param memView       The memory view\n     * @return words_       The number of memory words\n     */\n    function words(MemView memView) internal pure returns (uint256 words_) {\n        // returning ceil(length / 32.0)\n        unchecked {\n            return (memView.len() + 31) \u003e\u003e 5;\n        }\n    }\n\n    /**\n     * @notice Returns the in-memory footprint of a fresh copy of the view.\n     * @param memView       The memory view\n     * @return footprint_   The in-memory footprint of a fresh copy of the view.\n     */\n    function footprint(MemView memView) internal pure returns (uint256 footprint_) {\n        // words() * 32\n        return memView.words() \u003c\u003c 5;\n    }\n\n    // ════════════════════════════════════════════ HASHING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the keccak256 hash of the underlying memory\n     * @param memView       The memory view\n     * @return digest       The keccak256 hash of the underlying memory\n     */\n    function keccak(MemView memView) internal pure returns (bytes32 digest) {\n        uint256 loc_ = memView.loc();\n        uint256 len_ = memView.len();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            digest := keccak256(loc_, len_)\n        }\n    }\n\n    /**\n     * @notice Adds a salt to the keccak256 hash of the underlying data and returns the keccak256 hash of the\n     * resulting data.\n     * @param memView       The memory view\n     * @return digestSalted keccak256(salt, keccak256(memView))\n     */\n    function keccakSalted(MemView memView, bytes32 salt) internal pure returns (bytes32 digestSalted) {\n        return keccak256(bytes.concat(salt, memView.keccak()));\n    }\n\n    // ════════════════════════════════════════════ SLICING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Safe slicing without memory modification.\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the given index\n     */\n    function slice(MemView memView, uint256 index_, uint256 len_) internal pure returns (MemView) {\n        uint256 loc_ = memView.loc();\n        // Ensure it doesn't overrun the view\n        if (loc_ + index_ + len_ \u003e memView.end()) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // loc_ + index_ \u003c= memView.end()\n            return build({loc_: loc_ + index_, len_: len_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing bytes from `index` to end(memView).\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @return The new view for the slice starting from the given index until the initial view endpoint\n     */\n    function sliceFrom(MemView memView, uint256 index_) internal pure returns (MemView) {\n        uint256 len_ = memView.len();\n        // Ensure it doesn't overrun the view\n        if (index_ \u003e len_) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // index_ \u003c= len_ =\u003e memView.loc() + index_ \u003c= memView.loc() + memView.len() == memView.end()\n            return build({loc_: memView.loc() + index_, len_: len_ - index_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the first `len` bytes.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the initial view beginning\n     */\n    function prefix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        return memView.slice({index_: 0, len_: len_});\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the last `len` byte.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length until the initial view endpoint\n     */\n    function postfix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        uint256 viewLen = memView.len();\n        // Ensure it doesn't overrun the view\n        if (len_ \u003e viewLen) {\n            revert ViewOverrun();\n        }\n        // Could do the unchecked math due to the check above\n        uint256 index_;\n        unchecked {\n            index_ = viewLen - len_;\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // len_ \u003c= memView.len() =\u003e memView.loc() \u003c= loc_ \u003c= memView.end()\n            return build({loc_: memView.loc() + viewLen - len_, len_: len_});\n        }\n    }\n\n    // ═══════════════════════════════════════════ INDEXING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Load up to 32 bytes from the view onto the stack.\n     * @dev Returns a bytes32 with only the `bytes_` HIGHEST bytes set.\n     * This can be immediately cast to a smaller fixed-length byte array.\n     * To automatically cast to an integer, use `indexUint`.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return result       The 32 byte result having only `bytes_` highest bytes set\n     */\n    function index(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (bytes32 result) {\n        if (bytes_ == 0) {\n            return bytes32(0);\n        }\n        // Can't load more than 32 bytes to the stack in one go\n        if (bytes_ \u003e 32) {\n            revert IndexedTooMuch();\n        }\n        // The last indexed byte should be within view boundaries\n        if (index_ + bytes_ \u003e memView.len()) {\n            revert ViewOverrun();\n        }\n        uint256 bitLength = bytes_ \u003c\u003c 3; // bytes_ * 8\n        uint256 loc_ = memView.loc();\n        // Get a mask with `bitLength` highest bits set\n        uint256 mask;\n        // 0x800...00 binary representation is 100...00\n        // sar stands for \"signed arithmetic shift\": https://en.wikipedia.org/wiki/Arithmetic_shift\n        // sar(N-1, 100...00) = 11...100..00, with exactly N highest bits set to 1\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            mask := sar(sub(bitLength, 1), 0x8000000000000000000000000000000000000000000000000000000000000000)\n        }\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load a full word using index offset, and apply mask to ignore non-relevant bytes\n            result := and(mload(add(loc_, index_)), mask)\n        }\n    }\n\n    /**\n     * @notice Parse an unsigned integer from the view at `index`.\n     * @dev Requires that the view have \u003e= `bytes_` bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return The unsigned integer\n     */\n    function indexUint(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (uint256) {\n        bytes32 indexedBytes = memView.index(index_, bytes_);\n        // `index()` returns left-aligned `bytes_`, while integers are right-aligned\n        // Shifting here to right-align with the full 32 bytes word: need to shift right `(32 - bytes_)` bytes\n        unchecked {\n            // memView.index() reverts when bytes_ \u003e 32, thus unchecked math\n            return uint256(indexedBytes) \u003e\u003e ((32 - bytes_) \u003c\u003c 3);\n        }\n    }\n\n    /**\n     * @notice Parse an address from the view at `index`.\n     * @dev Requires that the view have \u003e= 20 bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @return The address\n     */\n    function indexAddress(MemView memView, uint256 index_) internal pure returns (address) {\n        // index 20 bytes as `uint160`, and then cast to `address`\n        return address(uint160(memView.indexUint(index_, 20)));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns a memory view over the specified memory location\n    /// without checking if it points to unallocated memory.\n    function _unsafeBuildUnchecked(uint256 loc_, uint256 len_) private pure returns (MemView) {\n        // There is no scenario where loc or len would overflow uint128, so we omit this check.\n        // We use the highest 128 bits to encode the location and the lowest 128 bits to encode the length.\n        return MemView.wrap((loc_ \u003c\u003c 128) | len_);\n    }\n\n    /**\n     * @notice Copy the view to a location, return an unsafe memory reference\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memView       The memory view\n     * @param newLoc        The new location to copy the underlying view data\n     * @return The memory view over the unsafe memory with the copied underlying data\n     */\n    function _unsafeCopyTo(MemView memView, uint256 newLoc) private view returns (MemView) {\n        uint256 len_ = memView.len();\n        uint256 oldLoc = memView.loc();\n\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (newLoc \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        bool res;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // use the identity precompile (0x04) to copy\n            res := staticcall(gas(), 0x04, oldLoc, len_, newLoc, len_)\n        }\n        if (!res) revert PrecompileOutOfGas();\n        return _unsafeBuildUnchecked({loc_: newLoc, len_: len_});\n    }\n\n    /**\n     * @notice Join the views in memory, return an unsafe reference to the memory.\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memViews      The memory views\n     * @return The conjoined view pointing to the new memory\n     */\n    function _unsafeJoin(MemView[] memory memViews, uint256 location) private view returns (MemView) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (location \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        // Copy the views to the specified location one by one, by tracking the amount of copied bytes so far\n        uint256 offset = 0;\n        for (uint256 i = 0; i \u003c memViews.length;) {\n            MemView memView = memViews[i];\n            // We can use the unchecked math here as location + sum(view.length) will never overflow uint256\n            unchecked {\n                _unsafeCopyTo(memView, location + offset);\n                offset += memView.len();\n                ++i;\n            }\n        }\n        return _unsafeBuildUnchecked({loc_: location, len_: offset});\n    }\n}\n\n// contracts/libs/merkle/MerkleMath.sol\n\nlibrary MerkleMath {\n    // ═════════════════════════════════════════ BASIC MERKLE CALCULATIONS ═════════════════════════════════════════════\n\n    /**\n     * @notice Calculates the merkle root for the given leaf and merkle proof.\n     * @dev Will revert if proof length exceeds the tree height.\n     * @param index     Index of `leaf` in tree\n     * @param leaf      Leaf of the merkle tree\n     * @param proof     Proof of inclusion of `leaf` in the tree\n     * @param height    Height of the merkle tree\n     * @return root_    Calculated Merkle Root\n     */\n    function proofRoot(uint256 index, bytes32 leaf, bytes32[] memory proof, uint256 height)\n        internal\n        pure\n        returns (bytes32 root_)\n    {\n        // Proof length could not exceed the tree height\n        uint256 proofLen = proof.length;\n        if (proofLen \u003e height) revert TreeHeightTooLow();\n        root_ = leaf;\n        /// @dev Apply unchecked to all ++h operations\n        unchecked {\n            // Go up the tree levels from the leaf following the proof\n            for (uint256 h = 0; h \u003c proofLen; ++h) {\n                // Get a sibling node on current level: this is proof[h]\n                root_ = getParent(root_, proof[h], index, h);\n            }\n            // Go up to the root: the remaining siblings are EMPTY\n            for (uint256 h = proofLen; h \u003c height; ++h) {\n                root_ = getParent(root_, bytes32(0), index, h);\n            }\n        }\n    }\n\n    /**\n     * @notice Calculates the parent of a node on the path from one of the leafs to root.\n     * @param node          Node on a path from tree leaf to root\n     * @param sibling       Sibling for a given node\n     * @param leafIndex     Index of the tree leaf\n     * @param nodeHeight    \"Level height\" for `node` (ZERO for leafs, ORIGIN_TREE_HEIGHT for root)\n     */\n    function getParent(bytes32 node, bytes32 sibling, uint256 leafIndex, uint256 nodeHeight)\n        internal\n        pure\n        returns (bytes32 parent)\n    {\n        // Index for `node` on its \"tree level\" is (leafIndex / 2**height)\n        // \"Left child\" has even index, \"right child\" has odd index\n        if ((leafIndex \u003e\u003e nodeHeight) \u0026 1 == 0) {\n            // Left child\n            return getParent(node, sibling);\n        } else {\n            // Right child\n            return getParent(sibling, node);\n        }\n    }\n\n    /// @notice Calculates the parent of tow nodes in the merkle tree.\n    /// @dev We use implementation with H(0,0) = 0\n    /// This makes EVERY empty node in the tree equal to ZERO,\n    /// saving us from storing H(0,0), H(H(0,0), H(0, 0)), and so on\n    /// @param leftChild    Left child of the calculated node\n    /// @param rightChild   Right child of the calculated node\n    /// @return parent      Value for the node having above mentioned children\n    function getParent(bytes32 leftChild, bytes32 rightChild) internal pure returns (bytes32 parent) {\n        if (leftChild == bytes32(0) \u0026\u0026 rightChild == bytes32(0)) {\n            return 0;\n        } else {\n            return keccak256(bytes.concat(leftChild, rightChild));\n        }\n    }\n\n    // ════════════════════════════════ ROOT/PROOF CALCULATION FOR A LIST OF LEAFS ═════════════════════════════════════\n\n    /**\n     * @notice Calculates merkle root for a list of given leafs.\n     * Merkle Tree is constructed by padding the list with ZERO values for leafs until list length is `2**height`.\n     * Merkle Root is calculated for the constructed tree, and then saved in `leafs[0]`.\n     * \u003e Note:\n     * \u003e - `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * \u003e - Caller is expected not to reuse `hashes` list after the call, and only use `leafs[0]` value,\n     * which is guaranteed to contain the calculated merkle root.\n     * \u003e - root is calculated using the `H(0,0) = 0` Merkle Tree implementation. See MerkleTree.sol for details.\n     * @dev Amount of leaves should be at most `2**height`\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param height    Height of the Merkle Tree to construct\n     */\n    function calculateRoot(bytes32[] memory hashes, uint256 height) internal pure {\n        uint256 levelLength = hashes.length;\n        // Amount of hashes could not exceed amount of leafs in tree with the given height\n        if (levelLength \u003e (1 \u003c\u003c height)) revert TreeHeightTooLow();\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\": the amount of iterations for the for loop above.\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n            }\n        }\n    }\n\n    /**\n     * @notice Generates a proof of inclusion of a leaf in the list. If the requested index is outside\n     * of the list range, generates a proof of inclusion for an empty leaf (proof of non-inclusion).\n     * The Merkle Tree is constructed by padding the list with ZERO values until list length is a power of two\n     * __AND__ index is in the extended list range. For example:\n     *  - `hashes.length == 6` and `0 \u003c= index \u003c= 7` will \"extend\" the list to 8 entries.\n     *  - `hashes.length == 6` and `7 \u003c index \u003c= 15` will \"extend\" the list to 16 entries.\n     * \u003e Note: `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * Caller is expected not to reuse `hashes` list after the call.\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param index     Leaf index to generate the proof for\n     * @return proof    Generated merkle proof\n     */\n    function calculateProof(bytes32[] memory hashes, uint256 index) internal pure returns (bytes32[] memory proof) {\n        // Use only meaningful values for the shortened proof\n        // Check if index is within the list range (we want to generates proofs for outside leafs as well)\n        uint256 height = getHeight(index \u003c hashes.length ? hashes.length : (index + 1));\n        proof = new bytes32[](height);\n        uint256 levelLength = hashes.length;\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Use sibling for the merkle proof; `index^1` is index of our sibling\n                proof[h] = (index ^ 1 \u003c levelLength) ? hashes[index ^ 1] : bytes32(0);\n\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\"\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n                // Traverse to parent node\n                index \u003e\u003e= 1;\n            }\n        }\n    }\n\n    /// @notice Returns the height of the tree having a given amount of leafs.\n    function getHeight(uint256 leafs) internal pure returns (uint256 height) {\n        uint256 amount = 1;\n        while (amount \u003c leafs) {\n            unchecked {\n                ++height;\n            }\n            amount \u003c\u003c= 1;\n        }\n    }\n}\n\n// contracts/libs/stack/GasData.sol\n\n/// GasData in encoded data with \"basic information about gas prices\" for some chain.\ntype GasData is uint96;\n\nusing GasDataLib for GasData global;\n\n/// ChainGas is encoded data with given chain's \"basic information about gas prices\".\ntype ChainGas is uint128;\n\nusing GasDataLib for ChainGas global;\n\n/// Library for encoding and decoding GasData and ChainGas structs.\n/// # GasData\n/// `GasData` is a struct to store the \"basic information about gas prices\", that could\n/// be later used to approximate the cost of a message execution, and thus derive the\n/// minimal tip values for sending a message to the chain.\n/// \u003e - `GasData` is supposed to be cached by `GasOracle` contract, allowing to store the\n/// \u003e approximates instead of the exact values, and thus save on storage costs.\n/// \u003e - For instance, if `GasOracle` only updates the values on +- 10% change, having an\n/// \u003e 0.4% error on the approximates would be acceptable.\n/// `GasData` is supposed to be included in the Origin's state, which are synced across\n/// chains using Agent-signed snapshots and attestations.\n/// ## GasData stack layout (from highest bits to lowest)\n///\n/// | Position   | Field        | Type   | Bytes | Description                                         |\n/// | ---------- | ------------ | ------ | ----- | --------------------------------------------------- |\n/// | (012..010] | gasPrice     | uint16 | 2     | Gas price for the chain (in Wei per gas unit)       |\n/// | (010..008] | dataPrice    | uint16 | 2     | Calldata price (in Wei per byte of content)         |\n/// | (008..006] | execBuffer   | uint16 | 2     | Tx fee safety buffer for message execution (in Wei) |\n/// | (006..004] | amortAttCost | uint16 | 2     | Amortized cost for attestation submission (in Wei)  |\n/// | (004..002] | etherPrice   | uint16 | 2     | Chain's Ether Price / Mainnet Ether Price (in BWAD) |\n/// | (002..000] | markup       | uint16 | 2     | Markup for the message execution (in BWAD)          |\n/// \u003e See Number.sol for more details on `Number` type and BWAD (binary WAD) math.\n///\n/// ## ChainGas stack layout (from highest bits to lowest)\n///\n/// | Position   | Field   | Type   | Bytes | Description      |\n/// | ---------- | ------- | ------ | ----- | ---------------- |\n/// | (016..004] | gasData | uint96 | 12    | Chain's gas data |\n/// | (004..000] | domain  | uint32 | 4     | Chain's domain   |\nlibrary GasDataLib {\n    /// @dev Amount of bits to shift to gasPrice field\n    uint96 private constant SHIFT_GAS_PRICE = 10 * 8;\n    /// @dev Amount of bits to shift to dataPrice field\n    uint96 private constant SHIFT_DATA_PRICE = 8 * 8;\n    /// @dev Amount of bits to shift to execBuffer field\n    uint96 private constant SHIFT_EXEC_BUFFER = 6 * 8;\n    /// @dev Amount of bits to shift to amortAttCost field\n    uint96 private constant SHIFT_AMORT_ATT_COST = 4 * 8;\n    /// @dev Amount of bits to shift to etherPrice field\n    uint96 private constant SHIFT_ETHER_PRICE = 2 * 8;\n\n    /// @dev Amount of bits to shift to gasData field\n    uint128 private constant SHIFT_GAS_DATA = 4 * 8;\n\n    // ═════════════════════════════════════════════════ GAS DATA ══════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded GasData struct with the given fields.\n    /// @param gasPrice_        Gas price for the chain (in Wei per gas unit)\n    /// @param dataPrice_       Calldata price (in Wei per byte of content)\n    /// @param execBuffer_      Tx fee safety buffer for message execution (in Wei)\n    /// @param amortAttCost_    Amortized cost for attestation submission (in Wei)\n    /// @param etherPrice_      Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n    /// @param markup_          Markup for the message execution (in BWAD)\n    function encodeGasData(\n        Number gasPrice_,\n        Number dataPrice_,\n        Number execBuffer_,\n        Number amortAttCost_,\n        Number etherPrice_,\n        Number markup_\n    ) internal pure returns (GasData) {\n        // Number type wraps uint16, so could safely be casted to uint96\n        // forgefmt: disable-next-item\n        return GasData.wrap(\n            uint96(Number.unwrap(gasPrice_)) \u003c\u003c SHIFT_GAS_PRICE |\n            uint96(Number.unwrap(dataPrice_)) \u003c\u003c SHIFT_DATA_PRICE |\n            uint96(Number.unwrap(execBuffer_)) \u003c\u003c SHIFT_EXEC_BUFFER |\n            uint96(Number.unwrap(amortAttCost_)) \u003c\u003c SHIFT_AMORT_ATT_COST |\n            uint96(Number.unwrap(etherPrice_)) \u003c\u003c SHIFT_ETHER_PRICE |\n            uint96(Number.unwrap(markup_))\n        );\n    }\n\n    /// @notice Wraps padded uint256 value into GasData struct.\n    function wrapGasData(uint256 paddedGasData) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(paddedGasData));\n    }\n\n    /// @notice Returns the gas price, in Wei per gas unit.\n    function gasPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_GAS_PRICE));\n    }\n\n    /// @notice Returns the calldata price, in Wei per byte of content.\n    function dataPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_DATA_PRICE));\n    }\n\n    /// @notice Returns the tx fee safety buffer for message execution, in Wei.\n    function execBuffer(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_EXEC_BUFFER));\n    }\n\n    /// @notice Returns the amortized cost for attestation submission, in Wei.\n    function amortAttCost(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_AMORT_ATT_COST));\n    }\n\n    /// @notice Returns the ratio of Chain's Ether Price / Mainnet Ether Price, in BWAD math.\n    function etherPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_ETHER_PRICE));\n    }\n\n    /// @notice Returns the markup for the message execution, in BWAD math.\n    function markup(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data)));\n    }\n\n    // ════════════════════════════════════════════════ CHAIN DATA ═════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded ChainGas struct with the given fields.\n    /// @param gasData_ Chain's gas data\n    /// @param domain_  Chain's domain\n    function encodeChainGas(GasData gasData_, uint32 domain_) internal pure returns (ChainGas) {\n        // GasData type wraps uint96, so could safely be casted to uint128\n        return ChainGas.wrap(uint128(GasData.unwrap(gasData_)) \u003c\u003c SHIFT_GAS_DATA | uint128(domain_));\n    }\n\n    /// @notice Wraps padded uint256 value into ChainGas struct.\n    function wrapChainGas(uint256 paddedChainGas) internal pure returns (ChainGas) {\n        // Casting to uint128 will truncate the highest bits, which is the behavior we want\n        return ChainGas.wrap(uint128(paddedChainGas));\n    }\n\n    /// @notice Returns the chain's gas data.\n    function gasData(ChainGas data) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(ChainGas.unwrap(data) \u003e\u003e SHIFT_GAS_DATA));\n    }\n\n    /// @notice Returns the chain's domain.\n    function domain(ChainGas data) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(ChainGas.unwrap(data));\n    }\n\n    /// @notice Returns the hash for the list of ChainGas structs.\n    function snapGasHash(ChainGas[] memory snapGas) internal pure returns (bytes32 snapGasHash_) {\n        // Use assembly to calculate the hash of the array without copying it\n        // ChainGas takes a single word of storage, thus ChainGas[] is stored in the following way:\n        // 0x00: length of the array, in words\n        // 0x20: first ChainGas struct\n        // 0x40: second ChainGas struct\n        // And so on...\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Find the location where the array data starts, we add 0x20 to skip the length field\n            let loc := add(snapGas, 0x20)\n            // Load the length of the array (in words).\n            // Shifting left 5 bits is equivalent to multiplying by 32: this converts from words to bytes.\n            let len := shl(5, mload(snapGas))\n            // Calculate the hash of the array\n            snapGasHash_ := keccak256(loc, len)\n        }\n    }\n}\n\n// contracts/libs/stack/Header.sol\n\n/// Header is encoded data with \"general routing information\".\ntype Header is uint136;\n\nusing HeaderLib for Header global;\n\n/// Types of messages supported by Origin-Destination\n/// - Base: message sent by protocol user, contains tips\n/// - Manager: message sent between AgentManager contracts located on different chains, no tips\nenum MessageFlag {\n    Base,\n    Manager\n}\n\nusing HeaderLib for MessageFlag global;\n\n/// Library for formatting _the header part_ of _the messages used by Origin and Destination_.\n/// - Header represents general information for routing a Message for Origin and Destination.\n/// - Header occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n///\n/// # Header stack layout (from highest bits to lowest)\n///\n/// | Position   | Field            | Type   | Bytes | Description                             |\n/// | ---------- | ---------------- | ------ | ----- | --------------------------------------- |\n/// | (017..016] | flag             | uint8  | 1     | Flag specifying the type of message     |\n/// | (016..012] | origin           | uint32 | 4     | Domain where message originated         |\n/// | (012..008] | nonce            | uint32 | 4     | Message nonce on the origin domain      |\n/// | (008..004] | destination      | uint32 | 4     | Domain where message will be executed   |\n/// | (004..000] | optimisticPeriod | uint32 | 4     | Optimistic period that will be enforced |\nlibrary HeaderLib {\n    /// @dev Amount of bits to shift to flag field\n    uint136 private constant SHIFT_FLAG = 16 * 8;\n    /// @dev Amount of bits to shift to origin field\n    uint136 private constant SHIFT_ORIGIN = 12 * 8;\n    /// @dev Amount of bits to shift to nonce field\n    uint136 private constant SHIFT_NONCE = 8 * 8;\n    /// @dev Amount of bits to shift to destination field\n    uint136 private constant SHIFT_DESTINATION = 4 * 8;\n\n    /// @notice Returns an encoded header with provided fields\n    /// @param origin_              Domain of origin chain\n    /// @param nonce_               Message nonce on origin chain\n    /// @param destination_         Domain of destination chain\n    /// @param optimisticPeriod_    Optimistic period for message execution\n    function encodeHeader(\n        MessageFlag flag_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint32 destination_,\n        uint32 optimisticPeriod_\n    ) internal pure returns (Header) {\n        // All casts below are upcasts, so they are safe\n        // forgefmt: disable-next-item\n        return Header.wrap(\n            uint136(uint8(flag_)) \u003c\u003c SHIFT_FLAG |\n            uint136(origin_) \u003c\u003c SHIFT_ORIGIN |\n            uint136(nonce_) \u003c\u003c SHIFT_NONCE |\n            uint136(destination_) \u003c\u003c SHIFT_DESTINATION |\n            uint136(optimisticPeriod_)\n        );\n    }\n\n    /// @notice Checks that the header is a valid encoded header.\n    function isHeader(uint256 paddedHeader) internal pure returns (bool) {\n        // Check that flag is within range\n        return _flag(paddedHeader) \u003c= uint8(type(MessageFlag).max);\n    }\n\n    /// @notice Wraps the padded encoded request into a Header-typed value.\n    /// @dev The \"padded\" header is simply an encoded header casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded headers\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedHeader) internal pure returns (Header) {\n        // Check that flag is within range\n        if (!isHeader(paddedHeader)) revert FlagOutOfRange();\n        // Casting to uint136 will truncate the highest bits, which is the behavior we want\n        return Header.wrap(uint136(paddedHeader));\n    }\n\n    /// @notice Returns header's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Header header) internal pure returns (bytes32 hashedHeader) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store header in scratch space\n            mstore(0, header)\n            // Compute hash of header padded to 32 bytes\n            hashedHeader := keccak256(0, 32)\n        }\n    }\n\n    // ══════════════════════════════════════════════ HEADER SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns header's flag field\n    function flag(Header header) internal pure returns (MessageFlag) {\n        // We check that flag is within range when wrapping the header, so this cast is safe\n        return MessageFlag(_flag(Header.unwrap(header)));\n    }\n\n    /// @notice Returns header's origin field\n    function origin(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_ORIGIN);\n    }\n\n    /// @notice Returns header's nonce field\n    function nonce(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_NONCE);\n    }\n\n    /// @notice Returns header's destination field\n    function destination(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_DESTINATION);\n    }\n\n    /// @notice Returns header's optimistic seconds field\n    function optimisticPeriod(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns header's flag field without casting to MessageFlag\n    function _flag(uint256 paddedHeader) private pure returns (uint8) {\n        // Casting to uint8 will truncate the highest bits, which is the behavior we want\n        return uint8(paddedHeader \u003e\u003e SHIFT_FLAG);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n     * constructor.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall \u0026\u0026 _initialized \u003c 1) || (!AddressUpgradeable.isContract(address(this)) \u0026\u0026 _initialized == 1),\n            \"Initializable: contract is already initialized\"\n        );\n        _initialized = 1;\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: setting the version to 255 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing \u0026\u0026 _initialized \u003c version, \"Initializable: contract is already initialized\");\n        _initialized = version;\n        _initializing = true;\n        _;\n        _initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        require(_initializing, \"Initializable: contract is not initializing\");\n        _;\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized != type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint8) {\n        return _initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _initializing;\n    }\n}\n\n// contracts/interfaces/IAgentManager.sol\n\ninterface IAgentManager {\n    /**\n     * @notice Allows Inbox to open a Dispute between a Guard and a Notary, if they are both not in Dispute already.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Guard or Notary is already in Dispute.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Allows Inbox to slash an agent, if their fraud was proven.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Domain doesn't match the saved agent domain.\n     * @param domain    Domain where the Agent is active\n     * @param agent     Address of the Agent\n     * @param prover    Address that initially provided fraud proof\n     */\n    function slashAgent(uint32 domain, address agent, address prover) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest known root of the Agent Merkle Tree.\n     */\n    function agentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns the number of opened Disputes.\n     * @dev This includes the Disputes that have been resolved already.\n     */\n    function getDisputesAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns information about the dispute with the given index.\n     * @dev Will revert if dispute with given index hasn't been opened yet.\n     * @param index             Dispute index\n     * @return guard            Address of the Guard in the Dispute\n     * @return notary           Address of the Notary in the Dispute\n     * @return slashedAgent     Address of the Agent who was slashed when Dispute was resolved\n     * @return fraudProver      Address who provided fraud proof to resolve the Dispute\n     * @return reportPayload    Raw payload with report data that led to the Dispute\n     * @return reportSignature  Guard signature for the report payload\n     */\n    function getDispute(uint256 index)\n        external\n        view\n        returns (\n            address guard,\n            address notary,\n            address slashedAgent,\n            address fraudProver,\n            bytes memory reportPayload,\n            bytes memory reportSignature\n        );\n\n    /**\n     * @notice Returns the current Dispute status of a given agent. See Structures.sol for details.\n     * @dev Every returned value will be set to zero if agent was not slashed and is not in Dispute.\n     * `rival` and `disputePtr` will be set to zero if the agent was slashed without being in Dispute.\n     * @param agent         Agent address\n     * @return flag         Flag describing the current Dispute status for the agent: None/Pending/Slashed\n     * @return rival        Address of the rival agent in the Dispute\n     * @return fraudProver  Address who provided fraud proof to resolve the Dispute\n     * @return disputePtr   Index of the opened Dispute PLUS ONE. Zero if agent is not in Dispute.\n     */\n    function disputeStatus(address agent)\n        external\n        view\n        returns (DisputeFlag flag, address rival, address fraudProver, uint256 disputePtr);\n}\n\n// contracts/interfaces/IAgentSecured.sol\n\ninterface IAgentSecured {\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * between a Guard and a Notary has been opened.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * has been resolved due to one of the agents being slashed.\n     * \u003e `rivalIndex` will be ZERO, if the slashed agent was not in the Dispute.\n     * @param slashedIndex  Index of the slashed agent in the Agent Merkle Tree\n     * @param rivalIndex    Index of the their Dispute Rival in the Agent Merkle Tree\n     */\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the address of the local AgentManager contract, which is treated as\n     * the \"source of truth\" for agent statuses.\n     */\n    function agentManager() external view returns (address);\n\n    /**\n     * @notice Returns the address of the local Inbox contract, which is treated as\n     * the \"source of truth\" for agent-signed statements.\n     * @dev Inbox passes verified agent statements to `IAgentSecured` contract.\n     */\n    function inbox() external view returns (address);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns (flag, openedAt, resolvedAt) that describes the latest status of\n     * the latest dispute for an agent with a given index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param agentIndex    Agent index in the Agent Merkle Tree\n     * @return              Latest dispute status for the given agent: (flag, openedAt, resolvedAt)\n     */\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory);\n}\n\n// contracts/libs/memory/ByteString.sol\n\n/// @dev CallData is a memory view over the payload to be used for an external call, i.e.\n/// recipient.call(callData). Its length is always (4 + 32 * N) bytes:\n/// - First 4 bytes represent the function selector.\n/// - 32 * N bytes represent N words that function arguments occupy.\ntype CallData is uint256;\n\n/// @dev Attach library functions to CallData\nusing ByteString for CallData global;\n\n/// @dev Signature is a memory view over a \"65 bytes\" array representing a ECDSA signature.\ntype Signature is uint256;\n\n/// @dev Attach library functions to Signature\nusing ByteString for Signature global;\n\nlibrary ByteString {\n    using MemViewLib for bytes;\n\n    /**\n     * @dev non-compact ECDSA signatures are enforced as of OZ 4.7.3\n     *\n     *      Signature payload memory layout\n     * [000 .. 032) r   bytes32 32 bytes\n     * [032 .. 064) s   bytes32 32 bytes\n     * [064 .. 065) v   uint8    1 byte\n     */\n    uint256 internal constant SIGNATURE_LENGTH = 65;\n    uint256 private constant OFFSET_R = 0;\n    uint256 private constant OFFSET_S = 32;\n    uint256 private constant OFFSET_V = 64;\n\n    /**\n     * @dev Calldata memory layout\n     * [000 .. 004) selector    bytes4  4 bytes\n     *      Optional: N function arguments\n     * [004 .. 036) arg1        bytes32 32 bytes\n     *      ..\n     * [AAA .. END) argN        bytes32 32 bytes\n     */\n    uint256 internal constant SELECTOR_LENGTH = 4;\n    uint256 private constant OFFSET_SELECTOR = 0;\n    uint256 private constant OFFSET_ARGUMENTS = SELECTOR_LENGTH;\n\n    // ═════════════════════════════════════════════════ SIGNATURE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the signature payload from the given values.\n     * @dev Using ByteString.formatSignature({r: r, s: s, v: v}) will make sure\n     * that params are given in the right order.\n     */\n    function formatSignature(bytes32 r, bytes32 s, uint8 v) internal pure returns (bytes memory) {\n        return abi.encodePacked(r, s, v);\n    }\n\n    /**\n     * @notice Returns a Signature view over for the given payload.\n     * @dev Will revert if the payload is not a signature.\n     */\n    function castToSignature(bytes memory payload) internal pure returns (Signature) {\n        return castToSignature(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Signature view.\n     * @dev Will revert if the memory view is not over a signature.\n     */\n    function castToSignature(MemView memView) internal pure returns (Signature) {\n        if (!isSignature(memView)) revert UnformattedSignature();\n        return Signature.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a signature\n     */\n    function isSignature(MemView memView) internal pure returns (bool) {\n        return memView.len() == SIGNATURE_LENGTH;\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Signature signature) internal pure returns (MemView) {\n        return MemView.wrap(Signature.unwrap(signature));\n    }\n\n    // ═════════════════════════════════════════════ SIGNATURE SLICING ═════════════════════════════════════════════════\n\n    /// @notice Unpacks signature payload into (r, s, v) parameters.\n    /// @dev Make sure to verify signature length with isSignature() beforehand.\n    function toRSV(Signature signature) internal pure returns (bytes32 r, bytes32 s, uint8 v) {\n        // Get the underlying memory view\n        MemView memView = unwrap(signature);\n        r = memView.index({index_: OFFSET_R, bytes_: 32});\n        s = memView.index({index_: OFFSET_S, bytes_: 32});\n        // Can be safely casted to uint8, since we index a single byte\n        v = uint8(memView.indexUint({index_: OFFSET_V, bytes_: 1}));\n    }\n\n    // ═════════════════════════════════════════════════ CALLDATA ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the calldata with the modified arguments:\n     * the existing arguments are prepended with the arguments from the prefix.\n     * @dev Given:\n     *  - `calldata = abi.encodeWithSelector(foo.selector, d, e);`\n     *  - `prefix = abi.encode(a, b, c);`\n     *  - `a`, `b`, `c` are arguments of static type (i.e. not dynamically sized ones)\n     *      Then:\n     *  - Function will return abi.encodeWithSelector(foo.selector, a, c, c, d, e)\n     *  - Returned calldata will trigger `foo(a, b, c, d, e)` when used for a contract call.\n     * Note: for clarification as to what types are considered static, see\n     * https://docs.soliditylang.org/en/latest/abi-spec.html#formal-specification-of-the-encoding\n     * @param callData  Calldata that needs to be modified\n     * @param prefix    ABI-encoded arguments to use as the first arguments in the new calldata\n     * @return Modified calldata having prefix as the first arguments.\n     */\n    function addPrefix(CallData callData, bytes memory prefix) internal view returns (bytes memory) {\n        // Prefix should occupy a whole amount of words in memory\n        if (!_fullWords(prefix.length)) revert UnformattedCallDataPrefix();\n        MemView[] memory views = new MemView[](3);\n        // Use payload's function selector\n        views[0] = abi.encodePacked(callData.callSelector()).ref();\n        // Use prefix as the first arguments\n        views[1] = prefix.ref();\n        // Use payload's remaining arguments\n        views[2] = callData.arguments();\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a CallData view over for the given payload.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(bytes memory payload) internal pure returns (CallData) {\n        return castToCallData(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a CallData view.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(MemView memView) internal pure returns (CallData) {\n        if (!isCallData(memView)) revert UnformattedCallData();\n        return CallData.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a valid calldata, i.e.\n     * a function selector, followed by arbitrary amount of arguments.\n     */\n    function isCallData(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Calldata should at least have a function selector\n        if (length \u003c SELECTOR_LENGTH) return false;\n        // The remainder of the calldata should be exactly N memory words (N \u003e= 0)\n        return _fullWords(length - SELECTOR_LENGTH);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(CallData callData) internal pure returns (MemView) {\n        return MemView.wrap(CallData.unwrap(callData));\n    }\n\n    /// @notice Returns callData's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(CallData callData) internal pure returns (bytes32) {\n        return callData.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ CALLDATA SLICING ══════════════════════════════════════════════════\n\n    /**\n     * @notice Returns amount of memory words (32 byte chunks) the function arguments\n     * occupy in the calldata.\n     * @dev This might differ from amount of arguments supplied, if any of the arguments\n     * occupies more than one memory slot. It is true, however, that argument part of the payload\n     * occupies exactly N words, even for dynamic types like `bytes`\n     */\n    function argumentWords(CallData callData) internal pure returns (uint256) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        // Equivalent of (length - SELECTOR_LENGTH) / 32\n        return (memView.len() - SELECTOR_LENGTH) \u003e\u003e 5;\n    }\n\n    /// @notice Returns selector for the provided calldata.\n    function callSelector(CallData callData) internal pure returns (bytes4) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return bytes4(memView.index({index_: OFFSET_SELECTOR, bytes_: SELECTOR_LENGTH}));\n    }\n\n    /// @notice Returns abi encoded arguments for the provided calldata.\n    function arguments(CallData callData) internal pure returns (MemView) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return memView.sliceFrom({index_: OFFSET_ARGUMENTS});\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if length is full amount of memory words (32 bytes).\n    function _fullWords(uint256 length) internal pure returns (bool) {\n        // The equivalent of length % 32 == 0\n        return length \u0026 31 == 0;\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n    function __Context_init() internal onlyInitializing {\n    }\n\n    function __Context_init_unchained() internal onlyInitializing {\n    }\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[50] private __gap;\n}\n\n// contracts/libs/merkle/MerkleTree.sol\n\n/// `BaseTree` is a struct representing incremental merkle tree.\n/// - Contains only the current branch.\n/// - The number of inserted leaves is stored externally, and is later supplied for tree operations.\n/// - Has a fixed height of `ORIGIN_TREE_HEIGHT`.\n/// - Can store up to `2 ** ORIGIN_TREE_HEIGHT - 1` leaves.\n/// \u003e Note: the hash function for the tree `H(x, y)` is defined as:\n/// \u003e - `H(0,0) = 0`\n/// \u003e - `H(x,y) = keccak256(x, y), when (x != 0 || y != 0)`\n/// ## Invariant for leafs\n/// - The leftmost empty leaf has `index == count`, where `count` is the amount of the inserted leafs so far.\n/// - Value for any empty leaf or node is bytes32(0).\n/// ## Invariant for current branch\n/// `branch[i]` is always the value of a node on the i-th level.\n/// Levels are numbered from leafs to root: `0 .. ORIGIN_TREE_HEIGHT`.\n/// `branch[i]` stores the value for the node, such that:\n//  - The node is a \"left child\" (e.g. has an even index).\n/// - The node must have two non-empty children.\n/// - Out of all level's \"left child\" nodes with \"non-empty children\",\n/// the one with the biggest index (the rightmost one) is stored as `branch[i]`.\n/// \u003e __`branch` could be used to form a proof of inclusion for the first empty leaf (`index == count`).__\n/// _Here is how:_\n/// - Let's walk along the path from the \"first empty leaf\" to the root.\n/// - i-th bit of the \"first empty leaf\" index (which is equal to `count`) determines if the path's node\n/// for this i-th level is a \"left child\" or a \"right child\".\n/// - i-th bit in `count` is 0 → we are the left child on this level → sibling is the right child\n/// that does not exist yet → `proof[i] = bytes32(0)`.\n/// - i-th bit in `count` is 1 → we are the right child on this level → sibling is the left child\n/// sibling is the rightmost \"left child\" node on the level → `proof[i] = branch[i]`.\n/// \u003e Therefore `proof[i] = (count \u0026 (1 \u003c\u003c i)) == 0 ? bytes32(0) : branch[i])`\nstruct BaseTree {\n    bytes32[ORIGIN_TREE_HEIGHT] branch;\n}\n\nusing MerkleTree for BaseTree global;\n\n/// `HistoricalTree` is an incremental merkle tree keeping track of its historical merkle roots.\n/// \u003e - `roots[N]` is the root of the tree after `N` leafs were inserted\n/// \u003e - `roots[0] == bytes32(0)`\n/// @param tree     Incremental merkle tree\n/// @param roots    Historical merkle roots of the tree\nstruct HistoricalTree {\n    BaseTree tree;\n    bytes32[] roots;\n}\n\nusing MerkleTree for HistoricalTree global;\n\n/// `DynamicTree` is a struct representing a Merkle Tree with `2**AGENT_TREE_HEIGHT` leaves.\n/// - A single operation is available: update value for leaf with an arbitrary index (which might be a non-empty leaf).\n/// - This is done by requesting the proof of inclusion for the old value, which is used to both\n/// verify the old value, and calculate the new root.\n/// \u003e Based on Original idea from [ER forum post](https://ethresear.ch/t/efficient-on-chain-dynamic-merkle-tree/11054).\nstruct DynamicTree {\n    bytes32 root;\n}\n\nusing MerkleTree for DynamicTree global;\n\n/// MerkleTree is work based on Nomad's Merkle.sol, which is used under MIT OR Apache-2.0\n/// [link](https://github.com/nomad-xyz/monorepo/blob/main/packages/contracts-core/contracts/libs/Merkle.sol).\n/// With the following changes:\n/// - Adapted for Solidity 0.8.x.\n/// - Amount of tree leaves stored externally.\n/// - Added thorough documentation.\n/// - `H(0,0) = 0` optimization from [ER forum post](https://ethresear.ch/t/optimizing-sparse-merkle-trees/3751/6).\n/// \u003e Nomad's Merkle.sol is work based on eth2 deposit contract, which is used under CC0-1.0\n///[link](https://github.com/ethereum/deposit_contract/blob/dev/deposit_contract/contracts/validator_registration.v.py).\n/// With the following changes:\n/// \u003e - Implemented in Solidity 0.7.6 (eth2 deposit contract implemented in Vyper).\n/// \u003e - `H() = keccak256()` is used as the hashing function instead of `sha256()`.\nlibrary MerkleTree {\n    /// @dev For root calculation we need at least one empty leaf, thus the minus one in the formula.\n    uint256 internal constant MAX_LEAVES = 2 ** ORIGIN_TREE_HEIGHT - 1;\n\n    // ═════════════════════════════════════════════════ BASE TREE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Inserts `node` into merkle tree\n     * @dev Reverts if tree is full\n     * @param newCount  Amount of inserted leaves in the tree after the insertion (i.e. current + 1)\n     * @param node      Element to insert into tree\n     */\n    function insertBase(BaseTree storage tree, uint256 newCount, bytes32 node) internal {\n        if (newCount \u003e MAX_LEAVES) revert MerkleTreeFull();\n        // We go up the tree following the branch from the empty leaf AFTER the just inserted one.\n        // We stop when we find the first \"right child\" node.\n        // Its sibling is now the rightmost \"left child\" node that has two non-empty children.\n        // Therefore we need to update `tree.branch` value on this level.\n        // One could see that `tree.branch` value on lower and higher levels remain unchanged.\n\n        // Loop invariant: `node` is the current level's value for the branch from JUST INSERTED leaf\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            if ((newCount \u0026 1) == 1) {\n                // Found the first \"right child\" node on the branch from EMPTY leaf\n                // `node` is the value for node on branch from JUST INSERTED leaf\n                // Which in this case is the \"left child\".\n                // We update tree.branch and exit\n                tree.branch[i] = node;\n                return;\n            }\n            // On the branch from EMPTY leaf this is still a \"left child\".\n            // Meaning on branch from JUST INSERTED leaf, `node` is a right child.\n            // We compute value for `node` parent using `tree.branch` invariant:\n            // This is the rightmost \"left child\" node, which would be sibling of `node`.\n            node = MerkleMath.getParent(tree.branch[i], node);\n            // Get the parent index, and go to the next tree level\n            newCount \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n        // As the loop should always end prematurely with the `return` statement,\n        // this code should be unreachable. We assert `false` just to be safe.\n        assert(false);\n    }\n\n    /**\n     * @notice Calculates and returns current root of the merkle tree.\n     * @param count     Current amount of inserted leaves in the tree\n     * @return current  Calculated root of `tree`\n     */\n    function rootBase(BaseTree storage tree, uint256 count) internal view returns (bytes32 current) {\n        // To calculate the root we follow the branch of first EMPTY leaf (index == count)\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            // Check if we are the left or the right child on the current level\n            if ((count \u0026 1) == 1) {\n                // We are the right child. Our sibling is the \"rightmost\" \"left-child\" node\n                // that has two non-empty children → sibling is `tree.branch[i]`\n                current = MerkleMath.getParent(tree.branch[i], current);\n            } else {\n                // We are the left child. Our sibling does not exist yet → sibling is EMPTY\n                current = MerkleMath.getParent(current, bytes32(0));\n            }\n            // Get the parent index, and go to the next tree level\n            count \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    // ══════════════════════════════════════════════ HISTORICAL TREE ══════════════════════════════════════════════════\n\n    /// @notice Initializes the historical roots for the tree by inserting an empty root.\n    // solhint-disable-next-line ordering\n    function initializeRoots(HistoricalTree storage tree) internal returns (bytes32 savedRoot) {\n        // This should only be called once, when the contract is initialized\n        assert(tree.roots.length == 0);\n        // Save root for empty merkle tree: bytes32(0)\n        tree.roots.push(savedRoot);\n    }\n\n    /// @notice Inserts a new leaf into the merkle tree.\n    /// @dev Reverts if tree is full.\n    /// @param node         Element to insert into tree\n    /// @return newRoot     Merkle root after the leaf was inserted\n    function insert(HistoricalTree storage tree, bytes32 node) internal returns (bytes32 newRoot) {\n        // Tree count after the new leaf will be inserted (we store roots[0] as root of empty tree)\n        uint256 newCount = tree.roots.length;\n        tree.tree.insertBase(newCount, node);\n        // Save the new root\n        newRoot = tree.tree.rootBase(newCount);\n        tree.roots.push(newRoot);\n    }\n\n    /// @notice Returns the historical root of the merkle tree.\n    /// @dev Reverts if not enough leafs have been inserted.\n    /// @param count            Amount of leafs in the tree at some point of time\n    /// @return historicalRoot  Merkle root after `count` leafs were inserted\n    function root(HistoricalTree storage tree, uint256 count) internal view returns (bytes32 historicalRoot) {\n        if (count \u003e= tree.roots.length) revert NotEnoughLeafs();\n        return tree.roots[count];\n    }\n\n    // ═══════════════════════════════════════════════ DYNAMIC TREE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Updates the value for the leaf with the given index in the Dynamic Merkle Tree.\n     * @dev Will revert if incorrect proof of inclusion for old value is supplied.\n     * @param tree          Dynamic merkle tree\n     * @param index         Index of the leaf to update\n     * @param oldValue      Previous value of the leaf\n     * @param branch        Proof of inclusion of previous value into the tree\n     * @param newValue      New leaf value to assign\n     * @return newRoot      New value for the Merkle Root after the leaf is updated\n     */\n    function update(\n        DynamicTree storage tree,\n        uint256 index,\n        bytes32 oldValue,\n        bytes32[] memory branch,\n        bytes32 newValue\n    ) internal returns (bytes32 newRoot) {\n        // Check that the old value + proof result in a correct root\n        if (MerkleMath.proofRoot(index, oldValue, branch, AGENT_TREE_HEIGHT) != tree.root) {\n            revert LeafNotProven();\n        }\n        // New root is new value + the same proof (values for sibling nodes are not updated)\n        newRoot = MerkleMath.proofRoot(index, newValue, branch, AGENT_TREE_HEIGHT);\n        // Write the new root\n        tree.root = newRoot;\n    }\n}\n\n// contracts/libs/stack/Tips.sol\n\n/// Tips is encoded data with \"tips paid for sending a base message\".\n/// Note: even though uint256 is also an underlying type for MemView, Tips is stored ON STACK.\ntype Tips is uint256;\n\nusing TipsLib for Tips global;\n\n/// # Tips\n/// Library for formatting _the tips part_ of _the base messages_.\n///\n/// ## How the tips are awarded\n/// Tips are paid for sending a base message, and are split across all the agents that\n/// made the message execution on destination chain possible.\n/// ### Summit tips\n/// Split between:\n///     - Guard posting a snapshot with state ST_G for the origin chain.\n///     - Notary posting a snapshot SN_N using ST_G. This creates attestation A.\n///     - Notary posting a message receipt after it is executed on destination chain.\n/// ### Attestation tips\n/// Paid to:\n///     - Notary posting attestation A to destination chain.\n/// ### Execution tips\n/// Paid to:\n///     - First executor performing a valid execution attempt (correct proofs, optimistic period over),\n///      using attestation A to prove message inclusion on origin chain, whether the recipient reverted or not.\n/// ### Delivery tips.\n/// Paid to:\n///     - Executor who successfully executed the message on destination chain.\n///\n/// ## Tips encoding\n/// - Tips occupy a single storage word, and thus are stored on stack instead of being stored in memory.\n/// - The actual tip values should be determined by multiplying stored values by divided by TIPS_MULTIPLIER=2**32.\n/// - Tips are packed into a single word of storage, while allowing real values up to ~8*10**28 for every tip category.\n/// \u003e The only downside is that the \"real tip values\" are now multiplies of ~4*10**9, which should be fine even for\n/// the chains with the most expensive gas currency.\n/// # Tips stack layout (from highest bits to lowest)\n///\n/// | Position   | Field          | Type   | Bytes | Description                                                |\n/// | ---------- | -------------- | ------ | ----- | ---------------------------------------------------------- |\n/// | (032..024] | summitTip      | uint64 | 8     | Tip for agents interacting with Summit contract            |\n/// | (024..016] | attestationTip | uint64 | 8     | Tip for Notary posting attestation to Destination contract |\n/// | (016..008] | executionTip   | uint64 | 8     | Tip for valid execution attempt on destination chain       |\n/// | (008..000] | deliveryTip    | uint64 | 8     | Tip for successful message delivery on destination chain   |\n\nlibrary TipsLib {\n    using SafeCast for uint256;\n\n    /// @dev Amount of bits to shift to summitTip field\n    uint256 private constant SHIFT_SUMMIT_TIP = 24 * 8;\n    /// @dev Amount of bits to shift to attestationTip field\n    uint256 private constant SHIFT_ATTESTATION_TIP = 16 * 8;\n    /// @dev Amount of bits to shift to executionTip field\n    uint256 private constant SHIFT_EXECUTION_TIP = 8 * 8;\n\n    // ═══════════════════════════════════════════════════ TIPS ════════════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips with the given fields\n    /// @param summitTip_        Tip for agents interacting with Summit contract, divided by TIPS_MULTIPLIER\n    /// @param attestationTip_   Tip for Notary posting attestation to Destination contract, divided by TIPS_MULTIPLIER\n    /// @param executionTip_     Tip for valid execution attempt on destination chain, divided by TIPS_MULTIPLIER\n    /// @param deliveryTip_      Tip for successful message delivery on destination chain, divided by TIPS_MULTIPLIER\n    function encodeTips(uint64 summitTip_, uint64 attestationTip_, uint64 executionTip_, uint64 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // forgefmt: disable-next-item\n        return Tips.wrap(\n            uint256(summitTip_) \u003c\u003c SHIFT_SUMMIT_TIP |\n            uint256(attestationTip_) \u003c\u003c SHIFT_ATTESTATION_TIP |\n            uint256(executionTip_) \u003c\u003c SHIFT_EXECUTION_TIP |\n            uint256(deliveryTip_)\n        );\n    }\n\n    /// @notice Convenience function to encode tips with uint256 values.\n    function encodeTips256(uint256 summitTip_, uint256 attestationTip_, uint256 executionTip_, uint256 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // In practice, the tips amounts are not supposed to be higher than 2**96, and with 32 bits of granularity\n        // using uint64 is enough to store the values. However, we still check for overflow just in case.\n        // TODO: consider using Number type to store the tips values.\n        return encodeTips({\n            summitTip_: (summitTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            attestationTip_: (attestationTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            executionTip_: (executionTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            deliveryTip_: (deliveryTip_ \u003e\u003e TIPS_GRANULARITY).toUint64()\n        });\n    }\n\n    /// @notice Wraps the padded encoded tips into a Tips-typed value.\n    /// @dev There is no actual padding here, as the underlying type is already uint256,\n    /// but we include this function for consistency and to be future-proof, if tips will eventually use anything\n    /// smaller than uint256.\n    function wrapPadded(uint256 paddedTips) internal pure returns (Tips) {\n        return Tips.wrap(paddedTips);\n    }\n\n    /**\n     * @notice Returns a formatted Tips payload specifying empty tips.\n     * @return Formatted tips\n     */\n    function emptyTips() internal pure returns (Tips) {\n        return Tips.wrap(0);\n    }\n\n    /// @notice Returns tips's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Tips tips) internal pure returns (bytes32 hashedTips) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store tips in scratch space\n            mstore(0, tips)\n            // Compute hash of tips padded to 32 bytes\n            hashedTips := keccak256(0, 32)\n        }\n    }\n\n    // ═══════════════════════════════════════════════ TIPS SLICING ════════════════════════════════════════════════════\n\n    /// @notice Returns summitTip field\n    function summitTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_SUMMIT_TIP);\n    }\n\n    /// @notice Returns attestationTip field\n    function attestationTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_ATTESTATION_TIP);\n    }\n\n    /// @notice Returns executionTip field\n    function executionTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_EXECUTION_TIP);\n    }\n\n    /// @notice Returns deliveryTip field\n    function deliveryTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips));\n    }\n\n    // ════════════════════════════════════════════════ TIPS VALUE ═════════════════════════════════════════════════════\n\n    /// @notice Returns total value of the tips payload.\n    /// This is the sum of the encoded values, scaled up by TIPS_MULTIPLIER\n    function value(Tips tips) internal pure returns (uint256 value_) {\n        value_ = uint256(tips.summitTip()) + tips.attestationTip() + tips.executionTip() + tips.deliveryTip();\n        value_ \u003c\u003c= TIPS_GRANULARITY;\n    }\n\n    /// @notice Increases the delivery tip to match the new value.\n    function matchValue(Tips tips, uint256 newValue) internal pure returns (Tips newTips) {\n        uint256 oldValue = tips.value();\n        if (newValue \u003c oldValue) revert TipsValueTooLow();\n        // We want to increase the delivery tip, while keeping the other tips the same\n        unchecked {\n            uint256 delta = (newValue - oldValue) \u003e\u003e TIPS_GRANULARITY;\n            // `delta` fits into uint224, as TIPS_GRANULARITY is 32, so this never overflows uint256.\n            // In practice, this will never overflow uint64 as well, but we still check it just in case.\n            if (delta + tips.deliveryTip() \u003e type(uint64).max) revert TipsOverflow();\n            // Delivery tips occupy lowest 8 bytes, so we can just add delta to the tips value\n            // to effectively increase the delivery tip (knowing that delta fits into uint64).\n            newTips = Tips.wrap(Tips.unwrap(tips) + delta);\n        }\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    function __Ownable_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable_init_unchained() internal onlyInitializing {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n    function __Ownable2Step_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable2Step_init_unchained() internal onlyInitializing {\n    }\n    address private _pendingOwner;\n\n    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Returns the address of the pending owner.\n     */\n    function pendingOwner() public view virtual returns (address) {\n        return _pendingOwner;\n    }\n\n    /**\n     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual override onlyOwner {\n        _pendingOwner = newOwner;\n        emit OwnershipTransferStarted(owner(), newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual override {\n        delete _pendingOwner;\n        super._transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev The new owner accepts the ownership transfer.\n     */\n    function acceptOwnership() public virtual {\n        address sender = _msgSender();\n        require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n        _transferOwnership(sender);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// contracts/libs/memory/State.sol\n\n/// State is a memory view over a formatted state payload.\ntype State is uint256;\n\nusing StateLib for State global;\n\n/// # State\n/// State structure represents the state of Origin contract at some point of time.\n/// - State is structured in a way to track the updates of the Origin Merkle Tree.\n/// - State includes root of the Origin Merkle Tree, origin domain and some additional metadata.\n/// ## Origin Merkle Tree\n/// Hash of every sent message is inserted in the Origin Merkle Tree, which changes\n/// the value of Origin Merkle Root (which is the root for the mentioned tree).\n/// - Origin has a single Merkle Tree for all messages, regardless of their destination domain.\n/// - This leads to Origin state being updated if and only if a message was sent in a block.\n/// - Origin contract is a \"source of truth\" for states: a state is considered \"valid\" in its Origin,\n/// if it matches the state of the Origin contract after the N-th (nonce) message was sent.\n///\n/// # Memory layout of State fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                    |\n/// | ---------- | ----------- | ------- | ----- | ------------------------------ |\n/// | [000..032) | root        | bytes32 | 32    | Root of the Origin Merkle Tree |\n/// | [032..036) | origin      | uint32  | 4     | Domain where Origin is located |\n/// | [036..040) | nonce       | uint32  | 4     | Amount of sent messages        |\n/// | [040..045) | blockNumber | uint40  | 5     | Block of last sent message     |\n/// | [045..050) | timestamp   | uint40  | 5     | Time of last sent message      |\n/// | [050..062) | gasData     | uint96  | 12    | Gas data for the chain         |\n///\n/// @dev State could be used to form a Snapshot to be signed by a Guard or a Notary.\nlibrary StateLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_ROOT = 0;\n    uint256 private constant OFFSET_ORIGIN = 32;\n    uint256 private constant OFFSET_NONCE = 36;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 40;\n    uint256 private constant OFFSET_TIMESTAMP = 45;\n    uint256 private constant OFFSET_GAS_DATA = 50;\n\n    // ═══════════════════════════════════════════════════ STATE ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted State payload with provided fields\n     * @param root_         New merkle root\n     * @param origin_       Domain of Origin's chain\n     * @param nonce_        Nonce of the merkle root\n     * @param blockNumber_  Block number when root was saved in Origin\n     * @param timestamp_    Block timestamp when root was saved in Origin\n     * @param gasData_      Gas data for the chain\n     * @return Formatted state\n     */\n    function formatState(\n        bytes32 root_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_,\n        GasData gasData_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(root_, origin_, nonce_, blockNumber_, timestamp_, gasData_);\n    }\n\n    /**\n     * @notice Returns a State view over the given payload.\n     * @dev Will revert if the payload is not a state.\n     */\n    function castToState(bytes memory payload) internal pure returns (State) {\n        return castToState(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a State view.\n     * @dev Will revert if the memory view is not over a state.\n     */\n    function castToState(MemView memView) internal pure returns (State) {\n        if (!isState(memView)) revert UnformattedState();\n        return State.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted State.\n    function isState(MemView memView) internal pure returns (bool) {\n        return memView.len() == STATE_LENGTH;\n    }\n\n    /// @notice Returns the hash of a State, that could be later signed by a Guard to signal\n    /// that the state is invalid.\n    function hashInvalid(State state) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(stateInvalidSalt, keccak(state))\n        return state.unwrap().keccakSalted(STATE_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(State state) internal pure returns (MemView) {\n        return MemView.wrap(State.unwrap(state));\n    }\n\n    /// @notice Compares two State structures.\n    function equals(State a, State b) internal pure returns (bool) {\n        // Length of a State payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═══════════════════════════════════════════════ STATE HASHING ═══════════════════════════════════════════════════\n\n    /// @notice Returns the hash of the State.\n    /// @dev We are using the Merkle Root of a tree with two leafs (see below) as state hash.\n    function leaf(State state) internal pure returns (bytes32) {\n        (bytes32 leftLeaf_, bytes32 rightLeaf_) = state.subLeafs();\n        // Final hash is the parent of these leafs\n        return keccak256(bytes.concat(leftLeaf_, rightLeaf_));\n    }\n\n    /// @notice Returns \"sub-leafs\" of the State. Hash of these \"sub leafs\" is going to be used\n    /// as a \"state leaf\" in the \"Snapshot Merkle Tree\".\n    /// This enables proving that leftLeaf = (root, origin) was a part of the \"Snapshot Merkle Tree\",\n    /// by combining `rightLeaf` with the remainder of the \"Snapshot Merkle Proof\".\n    function subLeafs(State state) internal pure returns (bytes32 leftLeaf_, bytes32 rightLeaf_) {\n        MemView memView = state.unwrap();\n        // Left leaf is (root, origin)\n        leftLeaf_ = memView.prefix({len_: OFFSET_NONCE}).keccak();\n        // Right leaf is (metadata), or (nonce, blockNumber, timestamp)\n        rightLeaf_ = memView.sliceFrom({index_: OFFSET_NONCE}).keccak();\n    }\n\n    /// @notice Returns the left \"sub-leaf\" of the State.\n    function leftLeaf(bytes32 root_, uint32 origin_) internal pure returns (bytes32) {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(root_, origin_));\n    }\n\n    /// @notice Returns the right \"sub-leaf\" of the State.\n    function rightLeaf(uint32 nonce_, uint40 blockNumber_, uint40 timestamp_, GasData gasData_)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(nonce_, blockNumber_, timestamp_, gasData_));\n    }\n\n    // ═══════════════════════════════════════════════ STATE SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns a historical Merkle root from the Origin contract.\n    function root(State state) internal pure returns (bytes32) {\n        return state.unwrap().index({index_: OFFSET_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns domain of chain where the Origin contract is deployed.\n    function origin(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns nonce of Origin contract at the time, when `root` was the Merkle root.\n    function nonce(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when `root` was saved in Origin.\n    function blockNumber(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when `root` was saved in Origin.\n    /// @dev This is the timestamp according to the origin chain.\n    function timestamp(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n\n    /// @notice Returns gas data for the chain.\n    function gasData(State state) internal pure returns (GasData) {\n        return GasDataLib.wrapGasData(state.unwrap().indexUint({index_: OFFSET_GAS_DATA, bytes_: GAS_DATA_LENGTH}));\n    }\n}\n\n// contracts/libs/memory/BaseMessage.sol\n\n/// BaseMessage is a memory view over the base message supported by Origin-Destination\ntype BaseMessage is uint256;\n\nusing BaseMessageLib for BaseMessage global;\n\n/// BaseMessage structure represents a base message sent via the Origin-Destination contracts.\n/// - It only contains data relevant to the base message, the rest of data is encoded in the message header.\n/// - `sender` and `recipient` for EVM chains are EVM addresses casted to bytes32, while preserving left-alignment.\n/// - `tips` and `request` parameters are specified by a message sender\n/// \u003e Origin will calculate minimum tips for given request and content length, and will reject messages with tips\n/// lower than that.\n///\n/// # Memory layout of BaseMessage fields\n///\n/// | Position   | Field     | Type    | Bytes | Description                            |\n/// | ---------- | --------- | ------- | ----- | -------------------------------------- |\n/// | [000..032) | tips      | uint256 | 32    | Encoded tips paid on origin chain      |\n/// | [032..064) | sender    | bytes32 | 32    | Sender address on origin chain         |\n/// | [064..096) | recipient | bytes32 | 32    | Recipient address on destination chain |\n/// | [096..116) | request   | uint160 | 20    | Encoded request for message execution  |\n/// | [104..AAA) | content   | bytes   | ??    | Content to be passed to recipient      |\nlibrary BaseMessageLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_TIPS = 0;\n    uint256 private constant OFFSET_SENDER = 32;\n    uint256 private constant OFFSET_RECIPIENT = 64;\n    uint256 private constant OFFSET_REQUEST = OFFSET_RECIPIENT + TIPS_LENGTH;\n    uint256 private constant OFFSET_CONTENT = OFFSET_REQUEST + REQUEST_LENGTH;\n\n    // ═══════════════════════════════════════════════ BASE MESSAGE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted BaseMessage payload with provided fields.\n     * @param tips_         Encoded tips information\n     * @param sender_       Sender address on origin chain\n     * @param recipient_    Recipient address on destination chain\n     * @param request_      Encoded request for message execution\n     * @param content_      Raw content to be passed to recipient on destination chain\n     * @return Formatted base message\n     */\n    function formatBaseMessage(Tips tips_, bytes32 sender_, bytes32 recipient_, Request request_, bytes memory content_)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return abi.encodePacked(tips_, sender_, recipient_, request_, content_);\n    }\n\n    /**\n     * @notice Returns a BaseMessage view over the given payload.\n     * @dev Will revert if the payload is not a base message.\n     */\n    function castToBaseMessage(bytes memory payload) internal pure returns (BaseMessage) {\n        return castToBaseMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a BaseMessage view.\n     * @dev Will revert if the memory view is not over a base message payload.\n     */\n    function castToBaseMessage(MemView memView) internal pure returns (BaseMessage) {\n        if (!isBaseMessage(memView)) revert UnformattedBaseMessage();\n        return BaseMessage.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted BaseMessage.\n    function isBaseMessage(MemView memView) internal pure returns (bool) {\n        // Check if sender, recipient, tips fields exist\n        return (memView.len() \u003e= OFFSET_CONTENT);\n        // Content could be empty, so we don't check that\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(BaseMessage baseMessage) internal pure returns (MemView) {\n        return MemView.wrap(BaseMessage.unwrap(baseMessage));\n    }\n\n    /// @notice Returns baseMessage's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        // We hash \"tips\" and \"everything but tips\" to make tips proofs easier to verify\n        return MerkleMath.getParent(baseMessage.tips().leaf(), baseMessage.bodyLeaf());\n    }\n\n    /// @notice Returns hash for the \"everything but tips\" part of the base message.\n    function bodyLeaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_SENDER}).keccak();\n    }\n\n    // ═══════════════════════════════════════════ BASE MESSAGE SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips paid on origin chain.\n    function tips(BaseMessage baseMessage) internal pure returns (Tips) {\n        return TipsLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_TIPS, bytes_: TIPS_LENGTH})));\n    }\n\n    /// @notice Returns sender address on origin chain.\n    function sender(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_SENDER, bytes_: 32});\n    }\n\n    /// @notice Returns recipient address on destination chain.\n    function recipient(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_RECIPIENT, bytes_: 32});\n    }\n\n    /// @notice Returns an encoded request for message execution on destination chain.\n    function request(BaseMessage baseMessage) internal pure returns (Request) {\n        return RequestLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_REQUEST, bytes_: REQUEST_LENGTH})));\n    }\n\n    /// @notice Returns an untyped memory view over the content to be passed to recipient.\n    function content(BaseMessage baseMessage) internal pure returns (MemView) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_CONTENT});\n    }\n}\n\n// contracts/base/MessagingBase.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for all messaging contracts.\n * - Provides context on the local chain's domain.\n * - Provides ownership functionality.\n * - Will be providing pausing functionality when it is implemented.\n */\nabstract contract MessagingBase is MultiCallable, Versioned, Ownable2StepUpgradeable {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @notice Domain of the local chain, set once upon contract creation\n    uint32 public immutable localDomain;\n    // @notice Domain of the Synapse chain, set once upon contract creation\n    uint32 public immutable synapseDomain;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev gap for upgrade safety\n    uint256[50] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    constructor(string memory version_, uint32 synapseDomain_) Versioned(version_) {\n        localDomain = ChainContext.chainId();\n        synapseDomain = synapseDomain_;\n    }\n\n    // TODO: Implement pausing\n\n    /**\n     * @dev Should be impossible to renounce ownership;\n     * we override OpenZeppelin OwnableUpgradeable's\n     * implementation of renounceOwnership to make it a no-op\n     */\n    function renounceOwnership() public override onlyOwner {} //solhint-disable-line no-empty-blocks\n}\n\n// contracts/libs/memory/Message.sol\n\n/// Message is a memory over over a formatted message payload.\ntype Message is uint256;\n\nusing MessageLib for Message global;\n\n/// Library for formatting the various messages supported by Origin and Destination.\n///\n/// # Message memory layout\n///\n/// | Position   | Field  | Type    | Bytes | Description                                             |\n/// | ---------- | ------ | ------- | ----- | ------------------------------------------------------- |\n/// | [000..017) | header | uint136 | 17    | Encoded general routing information for the message     |\n/// | [017..AAA) | body   | bytes   | ??    | Formatted payload (according to flag) with message body |\nlibrary MessageLib {\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MemViewLib for bytes;\n    using HeaderLib for MemView;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_HEADER = 0;\n    uint256 private constant OFFSET_BODY = OFFSET_HEADER + HEADER_LENGTH;\n\n    // ══════════════════════════════════════════════════ MESSAGE ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns formatted message with provided fields.\n     * @param header_   Encoded general routing information for the message\n     * @param body_     Formatted payload (according to flag) with message body\n     * @return Formatted message\n     */\n    function formatMessage(Header header_, bytes memory body_) internal pure returns (bytes memory) {\n        return abi.encodePacked(header_, body_);\n    }\n\n    /**\n     * @notice Returns a Message view over for the given payload.\n     * @dev Will revert if the payload is not a message payload.\n     */\n    function castToMessage(bytes memory payload) internal pure returns (Message) {\n        return castToMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Message view.\n     * @dev Will revert if the memory view is not over a message payload.\n     */\n    function castToMessage(MemView memView) internal pure returns (Message) {\n        if (!isMessage(memView)) revert UnformattedMessage();\n        return Message.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Message.\n     */\n    function isMessage(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Check if headers exist in the payload\n        if (length \u003c OFFSET_BODY) return false;\n        // Check that Header is valid\n        uint256 paddedHeader = _header(memView);\n        if (!HeaderLib.isHeader(paddedHeader)) return false;\n        // Check that body is formatted according to the flag\n        // Only Base/Manager message flags exist\n        if (HeaderLib.wrapPadded(paddedHeader).flag() == MessageFlag.Base) {\n            // Check if body is a formatted base message\n            return _body(memView).isBaseMessage();\n        } else {\n            // Check if body is a formatted calldata for AgentManager call\n            return _body(memView).isCallData();\n        }\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Message message) internal pure returns (MemView) {\n        return MemView.wrap(Message.unwrap(message));\n    }\n\n    /// @notice Returns message's hash: a leaf to be inserted in the Merkle tree.\n    function leaf(Message message) internal pure returns (bytes32) {\n        // We hash header and body separately to make message proofs easier to verify\n        Header header_ = message.header();\n        // Only Base/Manager message flags exist\n        if (header_.flag() == MessageFlag.Base) {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToBaseMessage().leaf());\n        } else {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToCallData().leaf());\n        }\n    }\n\n    // ══════════════════════════════════════════════ MESSAGE SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns message's encoded header field.\n    function header(Message message) internal pure returns (Header) {\n        return HeaderLib.wrapPadded((message.unwrap().indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH})));\n    }\n\n    /// @notice Returns message's body field as an untyped memory view.\n    function body(Message message) internal pure returns (MemView) {\n        MemView memView = message.unwrap();\n        return _body(memView);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns message's padded header without checking that it is a valid header.\n    function _header(MemView memView) private pure returns (uint256) {\n        return memView.indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH});\n    }\n\n    /// @dev Returns an untyped memory view over the body field without checking\n    /// if the whole payload or the body are properly formatted.\n    function _body(MemView memView) private pure returns (MemView) {\n        return memView.sliceFrom({index_: OFFSET_BODY});\n    }\n}\n\n// contracts/base/AgentSecured.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for messaging contracts that are secured by the agent manager.\n * `AgentSecured` relies on `AgentManager` to provide the following functionality:\n * - Keep track of agents and their statuses.\n * - Pass agent-signed statements that were verified by the agent manager.\n * - These statements are considered valid indefinitely, unless the agent is disputed.\n * - Disputes are opened and resolved by the agent manager.\n * \u003e `AgentSecured` implementation should never use statements signed by agents that are disputed.\n */\nabstract contract AgentSecured is MessagingBase, IAgentSecured {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    address public immutable agentManager;\n\n    /// @inheritdoc IAgentSecured\n    address public immutable inbox;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    // (agent index =\u003e their dispute status: flag, openedAt, resolvedAt)\n    mapping(uint32 =\u003e DisputeStatus) internal _disputes;\n\n    /// @dev gap for upgrade safety\n    uint256[49] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    modifier onlyAgentManager() {\n        if (msg.sender != agentManager) revert CallerNotAgentManager();\n        _;\n    }\n\n    modifier onlyInbox() {\n        if (msg.sender != inbox) revert CallerNotInbox();\n        _;\n    }\n\n    constructor(string memory version_, uint32 synapseDomain_, address agentManager_, address inbox_)\n        MessagingBase(version_, synapseDomain_)\n    {\n        agentManager = agentManager_;\n        inbox = inbox_;\n    }\n\n    // ════════════════════════════════════════════ ONLY AGENT MANAGER ═════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external onlyAgentManager {\n        uint40 openedAt = ChainContext.blockTimestamp();\n        DisputeStatus memory status = DisputeStatus({flag: DisputeFlag.Pending, openedAt: openedAt, resolvedAt: 0});\n        _disputes[guardIndex] = status;\n        _disputes[notaryIndex] = status;\n    }\n\n    /// @inheritdoc IAgentSecured\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external onlyAgentManager {\n        // Update the dispute status of the slashed agent first.\n        uint40 resolvedAt = ChainContext.blockTimestamp();\n        _disputes[slashedIndex].flag = DisputeFlag.Slashed;\n        _disputes[slashedIndex].resolvedAt = resolvedAt;\n        // Mark the rival agent as not disputed, if there was an ongoing dispute.\n        if (rivalIndex != 0) {\n            _disputes[rivalIndex].flag = DisputeFlag.None;\n            _disputes[rivalIndex].resolvedAt = resolvedAt;\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function agentStatus(address agent) external view returns (AgentStatus memory) {\n        return _agentStatus(agent);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status) {\n        return _getAgent(index);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory) {\n        return _disputes[agentIndex];\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns status of the given agent: (flag, domain, index).\n    function _agentStatus(address agent) internal view returns (AgentStatus memory) {\n        return IAgentManager(agentManager).agentStatus(agent);\n    }\n\n    /// @dev Returns agent and their status for a given agent index. Returns zero values for non existing indexes.\n    function _getAgent(uint256 index) internal view returns (address agent, AgentStatus memory status) {\n        return IAgentManager(agentManager).getAgent(index);\n    }\n\n    /// @dev Checks if a Dispute exists for the given Notary. This function returns true, if\n    /// Notary is in ongoing Dispute, or if Dispute was resolved not in Notary's favor.\n    /// In both cases we can't trust Notary's data.\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeExists(uint32 notaryIndex) internal view returns (bool) {\n        return _disputes[notaryIndex].flag != DisputeFlag.None;\n    }\n\n    /// @dev Checks if a Notary recently won a Dispute and is still in the \"post-dispute\" timeout period.\n    /// In this period we still can't trust Notary's data, though we can optimistically assume that\n    /// that the data will be correct after the timeout (assuming no new Disputes are opened).\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeTimeout(uint32 notaryIndex) internal view returns (bool) {\n        DisputeStatus memory status = _disputes[notaryIndex];\n        // Exit early if Notary is in ongoing Dispute / slashed.\n        if (status.flag != DisputeFlag.None) return false;\n        // Check if Notary has been in any Dispute at all.\n        if (status.openedAt == 0) return false;\n        // Otherwise check if the Dispute timeout is still active.\n        return block.timestamp \u003c status.resolvedAt + DISPUTE_TIMEOUT_NOTARY;\n    }\n}\n\n// contracts/hubs/StateHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StateHub` is a parent contract for `Origin`. It is responsible for the following:\n/// - Keeping track of the historical Origin Merkle Tree containing all the message hashes.\n/// - Keeping track of the historical Origin States, as well as verifying their validity.\nabstract contract StateHub is AgentSecured, StateHubEvents, IStateHub {\n    using SafeCast for uint256;\n    using StateLib for bytes;\n\n    struct OriginState {\n        uint40 blockNumber;\n        uint40 timestamp;\n        GasData gasData;\n    }\n    // Bits left for tight packing: 80\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Historical Merkle Tree\n    /// Note: Takes two storage slots\n    HistoricalTree private _tree;\n\n    /// @dev All historical contract States\n    OriginState[] private _originStates;\n\n    /// @dev gap for upgrade safety\n    uint256[47] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IStateHub\n    function isValidState(bytes memory statePayload) external view returns (bool isValid) {\n        // This will revert if payload is not a formatted state\n        State state = statePayload.castToState();\n        return _isValidState(state);\n    }\n\n    /// @inheritdoc IStateHub\n    function statesAmount() external view returns (uint256) {\n        return _originStates.length;\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestLatestState() external view returns (bytes memory stateData) {\n        // This never underflows, assuming the contract was initialized\n        return suggestState(_nextNonce() - 1);\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestState(uint32 nonce) public view returns (bytes memory stateData) {\n        // This will revert if nonce is out of range\n        bytes32 root = _tree.root(nonce);\n        return _formatOriginState(_originStates[nonce], root, localDomain, nonce);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Initializes the saved states list by inserting a state for an empty Merkle Tree.\n    function _initializeStates() internal {\n        // This should only be called once, when the contract is initialized\n        // This will revert if _tree.roots is non-empty\n        bytes32 savedRoot = _tree.initializeRoots();\n        // Save root for empty merkle _tree with block number and timestamp of initialization\n        _saveState(savedRoot, _toOriginState());\n    }\n\n    /// @dev Inserts leaf into the Merkle Tree and saves the updated origin State.\n    function _insertAndSave(bytes32 leaf) internal {\n        bytes32 newRoot = _tree.insert(leaf);\n        _saveState(newRoot, _toOriginState());\n    }\n\n    /// @dev Saves an updated state of the Origin contract\n    function _saveState(bytes32 root, OriginState memory state) internal {\n        uint32 nonce = _nextNonce();\n        _originStates.push(state);\n        // Emit event with raw state data\n        emit StateSaved(_formatOriginState(state, root, localDomain, nonce));\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns nonce of the next sent message: the amount of saved States so far.\n    /// This always equals to \"total amount of sent messages\" plus 1.\n    function _nextNonce() internal view returns (uint32) {\n        // TODO: consider using more than 32 bits for origin nonces\n        return _originStates.length.toUint32();\n    }\n\n    /// @dev Checks if a state is valid, i.e. if it matches the historical one.\n    /// Reverts, if state refers to another Origin contract.\n    function _isValidState(State state) internal view returns (bool) {\n        // Check if state refers to this contract\n        if (state.origin() != localDomain) revert IncorrectOriginDomain();\n        // Check if nonce exists\n        uint32 nonce = state.nonce();\n        if (nonce \u003e= _originStates.length) return false;\n        // Check if state root matches the historical one\n        if (state.root() != _tree.root(nonce)) return false;\n        // Check if state metadata matches the historical one\n        return _areEqual(state, _originStates[nonce]);\n    }\n\n    // ═════════════════════════════════════════════ STRUCT FORMATTING ═════════════════════════════════════════════════\n\n    /// @dev Returns a formatted payload for a stored OriginState.\n    function _formatOriginState(OriginState memory originState, bytes32 root, uint32 origin, uint32 nonce)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return StateLib.formatState({\n            root_: root,\n            origin_: origin,\n            nonce_: nonce,\n            blockNumber_: originState.blockNumber,\n            timestamp_: originState.timestamp,\n            gasData_: originState.gasData\n        });\n    }\n\n    /// @dev Child contract should implement the logic for getting the current gas data from the gas oracle\n    /// to be saved as part of the Origin State.\n    // solhint-disable-next-line ordering\n    function _fetchGasData() internal view virtual returns (GasData);\n\n    /// @dev Returns a OriginState struct to save in the contract.\n    function _toOriginState() internal view returns (OriginState memory originState) {\n        originState.blockNumber = ChainContext.blockNumber();\n        originState.timestamp = ChainContext.blockTimestamp();\n        originState.gasData = _fetchGasData();\n    }\n\n    /// @dev Checks that a state and its Origin representation are equal.\n    function _areEqual(State state, OriginState memory originState) internal pure returns (bool) {\n        return state.blockNumber() == originState.blockNumber \u0026\u0026 state.timestamp() == originState.timestamp;\n    }\n}\n\n// contracts/Origin.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Origin` contract is used for sending messages to remote chains. It is done\n/// by inserting the message hashes into the Origin Merkle, which makes it possible to\n/// prove that message was sent using the Merkle proof against the Origin Merkle Root. This essentially\n/// compresses the list of messages into a single 32-byte value that needs to be stored on the destination chain.\n/// `Origin` is responsible for the following:\n/// - Formatting the sent message payloads, and inserting their hashes into the Origin Merkle Tree.\n/// - Keeping track of its own historical states (see parent contract `StateHub`).\n/// - Enforcing minimum tip values for sent base messages based on the provided execution requests.\n/// - Distributing the collected tips upon request from a local `AgentManager` contract.\ncontract Origin is StateHub, OriginEvents, InterfaceOrigin {\n    using MemViewLib for bytes;\n    using MessageLib for bytes;\n    using TipsLib for bytes;\n    using TypeCasts for address;\n\n    address public immutable gasOracle;\n\n    modifier onlyRemoteDestination(uint32 destination) {\n        if (destination == localDomain) revert IncorrectDestinationDomain();\n        _;\n    }\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_, address gasOracle_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {\n        gasOracle = gasOracle_;\n    }\n\n    /// @notice Initializes Origin contract:\n    /// - msg.sender is set as contract owner\n    /// - State of \"empty merkle tree\" is saved\n    function initialize() external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize \"states\": state of an \"empty merkle tree\" is saved\n        _initializeStates();\n    }\n\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable onlyRemoteDestination(destination) returns (uint32 messageNonce, bytes32 messageHash) {\n        // Check that content is not too large\n        if (content.length \u003e MAX_CONTENT_BYTES) revert ContentLengthTooBig();\n        // This will revert if msg.value is lower than value of minimum tips\n        Tips tips = _getMinimumTips(destination, paddedRequest, content.length).matchValue(msg.value);\n        Request request = RequestLib.wrapPadded(paddedRequest);\n        // Format the BaseMessage body\n        bytes memory body = BaseMessageLib.formatBaseMessage({\n            sender_: msg.sender.addressToBytes32(),\n            recipient_: recipient,\n            tips_: tips,\n            request_: request,\n            content_: content\n        });\n        // Send the message\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Base, body);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        onlyAgentManager\n        onlyRemoteDestination(destination)\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // AgentManager (checked via modifier) is responsible for constructing the calldata payload correctly.\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Manager, payload);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function withdrawTips(address recipient, uint256 amount) external onlyAgentManager {\n        if (address(this).balance \u003c amount) revert InsufficientEthBalance();\n        (bool success,) = recipient.call{value: amount}(\"\");\n        if (!success) revert EthTransferFailed();\n        emit TipWithdrawalCompleted(recipient, amount);\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue)\n    {\n        return _getMinimumTips(destination, paddedRequest, contentLength).value();\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Sends the given message to the specified destination. Message hash is inserted\n    /// into the Origin Merkle Tree, which will enable message execution on destination chain.\n    function _sendMessage(uint32 destination, uint32 optimisticPeriod, MessageFlag flag, bytes memory body)\n        internal\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // Format the message header\n        messageNonce = _nextNonce();\n        Header header = flag.encodeHeader({\n            origin_: localDomain,\n            nonce_: messageNonce,\n            destination_: destination,\n            optimisticPeriod_: optimisticPeriod\n        });\n        // Format the full message payload\n        bytes memory msgPayload = MessageLib.formatMessage(header, body);\n        // Insert new leaf into the Origin Merkle Tree and save the updated state\n        messageHash = msgPayload.castToMessage().leaf();\n        _insertAndSave(messageHash);\n        // Emit event with message information\n        emit Sent(messageHash, messageNonce, destination, msgPayload);\n        // Update the gas oracle data. We do this after the provided tips are checked so that\n        // the provided message is sent in the event that the gas oracle data is updated to a higher value.\n        InterfaceGasOracle(gasOracle).updateGasData(destination);\n        // TODO: consider doing this before the message is sent, while adjusting GasOracle.getMinimumTips() to\n        // use the pending gas oracle data.\n    }\n\n    /// @dev Returns the minimum tips for sending a message to the given destination with the given request and content.\n    function _getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        internal\n        view\n        returns (Tips)\n    {\n        return\n            TipsLib.wrapPadded(InterfaceGasOracle(gasOracle).getMinimumTips(destination, paddedRequest, contentLength));\n    }\n\n    /// @dev Gets the current gas data from the gas oracle to be saved as part of the Origin State.\n    function _fetchGasData() internal view override returns (GasData) {\n        return GasDataLib.wrapGasData(InterfaceGasOracle(gasOracle).getGasData());\n    }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[{"internalType":"bytes","name":"statePayload","type":"bytes"}],"name":"isValidState","outputs":[{"internalType":"bool","name":"isValid","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"statesAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"suggestLatestState","outputs":[{"internalType":"bytes","name":"statePayload","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"nonce","type":"uint32"}],"name":"suggestState","outputs":[{"internalType":"bytes","name":"statePayload","type":"bytes"}],"stateMutability":"view","type":"function"}],"userDoc":{"kind":"user","methods":{"isValidState(bytes)":{"notice":"Check that a given state is valid: matches the historical state of Origin contract. Note: any Agent including an invalid state in their snapshot will be slashed upon providing the snapshot and agent signature for it to Origin contract."},"statesAmount()":{"notice":"Returns the amount of saved states so far."},"suggestLatestState()":{"notice":"Suggest the data (state after latest sent message) to sign for an Agent. Note: signing the suggested state data will will never lead to slashing of the actor, assuming they have confirmed that the block, which number is included in the data, is not subject to reorganization (which is different for every observed chain)."},"suggestState(uint32)":{"notice":"Given the historical nonce, suggest the state data to sign for an Agent. Note: signing the suggested state data will will never lead to slashing of the actor, assuming they have confirmed that the block, which number is included in the data, is not subject to reorganization (which is different for every observed chain)."}},"version":1},"developerDoc":{"kind":"dev","methods":{"isValidState(bytes)":{"details":"Will revert if any of these is true:  - State payload is not properly formatted.","params":{"statePayload":"Raw payload with state data"},"returns":{"isValid":"         Whether the provided state is valid"}},"statesAmount()":{"details":"This includes the initial state of \"empty Origin Merkle Tree\"."},"suggestLatestState()":{"returns":{"statePayload":"    Raw payload with the latest state data"}},"suggestState(uint32)":{"params":{"nonce":"Historical nonce to form a state"},"returns":{"statePayload":"    Raw payload with historical state data"}}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"statePayload\",\"type\":\"bytes\"}],\"name\":\"isValidState\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isValid\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"statesAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"suggestLatestState\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"statePayload\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"nonce\",\"type\":\"uint32\"}],\"name\":\"suggestState\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"statePayload\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"isValidState(bytes)\":{\"details\":\"Will revert if any of these is true:  - State payload is not properly formatted.\",\"params\":{\"statePayload\":\"Raw payload with state data\"},\"returns\":{\"isValid\":\"         Whether the provided state is valid\"}},\"statesAmount()\":{\"details\":\"This includes the initial state of \\\"empty Origin Merkle Tree\\\".\"},\"suggestLatestState()\":{\"returns\":{\"statePayload\":\"    Raw payload with the latest state data\"}},\"suggestState(uint32)\":{\"params\":{\"nonce\":\"Historical nonce to form a state\"},\"returns\":{\"statePayload\":\"    Raw payload with historical state data\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"isValidState(bytes)\":{\"notice\":\"Check that a given state is valid: matches the historical state of Origin contract. Note: any Agent including an invalid state in their snapshot will be slashed upon providing the snapshot and agent signature for it to Origin contract.\"},\"statesAmount()\":{\"notice\":\"Returns the amount of saved states so far.\"},\"suggestLatestState()\":{\"notice\":\"Suggest the data (state after latest sent message) to sign for an Agent. Note: signing the suggested state data will will never lead to slashing of the actor, assuming they have confirmed that the block, which number is included in the data, is not subject to reorganization (which is different for every observed chain).\"},\"suggestState(uint32)\":{\"notice\":\"Given the historical nonce, suggest the state data to sign for an Agent. Note: signing the suggested state data will will never lead to slashing of the actor, assuming they have confirmed that the block, which number is included in the data, is not subject to reorganization (which is different for every observed chain).\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Origin.sol\":\"IStateHub\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Origin.sol\":{\"keccak256\":\"0x96775924f147f3d1f8df8cdf56731fe52a15af8d8e12e608efb8158c112b18cd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e642a27f5fab3c62b4c02e9754e9e42b1cf2e5381dbea9d3d106d23b7772ebe6\",\"dweb:/ipfs/QmUwn7ZyBvPkjnMuK8ZMSexBUdNQnVtxwyoAyT4DXLQjra\"]}},\"version\":1}"},"hashes":{"isValidState(bytes)":"a9dcf22d","statesAmount()":"f2437942","suggestLatestState()":"c0b56f7c","suggestState(uint32)":"b4596b4b"}},"solidity/Origin.sol:Initializable":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/OriginEvents.sol\n\n/// @notice A collection of events emitted by the Origin contract\nabstract contract OriginEvents {\n    /**\n     * @notice Emitted when a new message is sent.\n     * @param messageHash   Hash of message; the leaf inserted to the Merkle tree for the message\n     * @param nonce         Nonce of sent message (starts from 1)\n     * @param destination   Destination domain\n     * @param message       Raw bytes of message\n     */\n    event Sent(bytes32 indexed messageHash, uint32 indexed nonce, uint32 indexed destination, bytes message);\n\n    /**\n     * @notice Emitted when a tip withdrawal is completed.\n     * @param actor     Actor address\n     * @param tip       Tip value, denominated in local domain's wei\n     */\n    event TipWithdrawalCompleted(address actor, uint256 tip);\n}\n\n// contracts/events/StateHubEvents.sol\n\n/// @notice A collection of events emitted by the StateHub contract\nabstract contract StateHubEvents {\n    /**\n     * @notice Emitted when a new Origin State is saved after a message was sent.\n     * @param state     Raw payload with state data\n     */\n    event StateSaved(bytes state);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n    /**\n     * @notice Check that a given state is valid: matches the historical state of Origin contract.\n     * Note: any Agent including an invalid state in their snapshot will be slashed\n     * upon providing the snapshot and agent signature for it to Origin contract.\n     * @dev Will revert if any of these is true:\n     *  - State payload is not properly formatted.\n     * @param statePayload      Raw payload with state data\n     * @return isValid          Whether the provided state is valid\n     */\n    function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns the amount of saved states so far.\n     * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n     */\n    function statesAmount() external view returns (uint256);\n\n    /**\n     * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @return statePayload     Raw payload with the latest state data\n     */\n    function suggestLatestState() external view returns (bytes memory statePayload);\n\n    /**\n     * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @param nonce             Historical nonce to form a state\n     * @return statePayload     Raw payload with historical state data\n     */\n    function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/InterfaceGasOracle.sol\n\ninterface InterfaceGasOracle {\n    /**\n     * @notice Fetches the latest gas data for the chain from `Destination` contract,\n     * and uses it to update the oracle values for the requested chain.\n     * @param domain    Domain to update the gas data for\n     */\n    function updateGasData(uint32 domain) external;\n\n    /**\n     * @notice Returns the gas data for the local chain.\n     */\n    function getGasData() external view returns (uint256 paddedGasData);\n\n    /**\n     * @notice Returns the gas data for the given domain, in the decoded format.\n     * @param domain        Domain of chain to get gas data for\n     * @return gasPrice     Gas price for the chain (in Wei per gas unit)\n     * @return dataPrice    Calldata price (in Wei per byte of content)\n     * @return execBuffer   Tx fee safety buffer for message execution (in Wei)\n     * @return amortAttCost Amortized cost for attestation submission (in Wei)\n     * @return etherPrice   Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n     * @return markup       Markup for the message execution (in BWAD)\n     */\n    function getDecodedGasData(uint32 domain)\n        external\n        view\n        returns (\n            uint256 gasPrice,\n            uint256 dataPrice,\n            uint256 execBuffer,\n            uint256 amortAttCost,\n            uint256 etherPrice,\n            uint256 markup\n        );\n\n    /**\n     * @notice Returns the minimum tips for sending a message to a given destination.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return paddedTips       Padded encoded minimum tips information\n     */\n    function getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 paddedTips);\n}\n\n// contracts/interfaces/InterfaceOrigin.sol\n\ninterface InterfaceOrigin {\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /**\n     * @notice Send a message to the recipient located on destination domain.\n     * @dev Recipient has to conform to IMessageRecipient interface, otherwise message won't be delivered.\n     * Will revert if any of these is true:\n     * - `destination` is equal to contract's local domain\n     * - `content` length is greater than `MAX_CONTENT_BYTES`\n     * - `msg.value` is lower than value of minimum tips for the given message\n     * @param destination           Domain of destination chain\n     * @param recipient             Address of recipient on destination chain as bytes32\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param paddedRequest         Padded encoded message execution request on destination chain\n     * @param content               Raw bytes content of message\n     * @return messageNonce         Nonce of the sent message\n     * @return messageHash          Hash of the sent message\n     */\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable returns (uint32 messageNonce, bytes32 messageHash);\n\n    /**\n     * @notice Send a manager message to the destination domain.\n     * @dev This could only be called by AgentManager, which takes care of encoding the calldata payload.\n     * Note: (msgOrigin, proofMaturity) security args will be added to payload on the destination chain\n     * so that the AgentManager could verify where the Manager Message came from and how mature is the proof.\n     * Note: function is not payable, as no tips are required for sending a manager message.\n     * Will revert if `destination` is equal to contract's local domain.\n     * @param destination           Domain of destination chain\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param payload               Payload for calling AgentManager on destination chain (with extra security args)\n     */\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        returns (uint32 messageNonce, bytes32 messageHash);\n\n    // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Withdraws locked base message tips to the recipient.\n     * @dev Could only be called by a local AgentManager.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function withdrawTips(address recipient, uint256 amount) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the minimum tips value for sending a message to a given destination.\n     * @dev Using at least `tipsValue` as `msg.value` for `sendBaseMessage()`\n     * will guarantee that the message will be accepted.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return tipsValue        Minimum tips value for a message to be accepted\n     */\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue);\n}\n\n// contracts/libs/Constants.sol\n\n// Here we define common constants to enable their easier reusing later.\n\n// ══════════════════════════════════ MERKLE ═══════════════════════════════════\n/// @dev Height of the Agent Merkle Tree\nuint256 constant AGENT_TREE_HEIGHT = 32;\n/// @dev Height of the Origin Merkle Tree\nuint256 constant ORIGIN_TREE_HEIGHT = 32;\n/// @dev Height of the Snapshot Merkle Tree. Allows up to 64 leafs, e.g. up to 32 states\nuint256 constant SNAPSHOT_TREE_HEIGHT = 6;\n// ══════════════════════════════════ STRUCTS ══════════════════════════════════\n/// @dev See Attestation.sol: (bytes32,bytes32,uint32,uint40,uint40): 32+32+4+5+5\nuint256 constant ATTESTATION_LENGTH = 78;\n/// @dev See GasData.sol: (uint16,uint16,uint16,uint16,uint16,uint16): 2+2+2+2+2+2\nuint256 constant GAS_DATA_LENGTH = 12;\n/// @dev See Receipt.sol: (uint32,uint32,bytes32,bytes32,uint8,address,address,address): 4+4+32+32+1+20+20+20\nuint256 constant RECEIPT_LENGTH = 133;\n/// @dev See State.sol: (bytes32,uint32,uint32,uint40,uint40,GasData): 32+4+4+5+5+len(GasData)\nuint256 constant STATE_LENGTH = 50 + GAS_DATA_LENGTH;\n/// @dev Maximum amount of states in a single snapshot. Each state produces two leafs in the tree\nuint256 constant SNAPSHOT_MAX_STATES = 1 \u003c\u003c (SNAPSHOT_TREE_HEIGHT - 1);\n// ══════════════════════════════════ MESSAGE ══════════════════════════════════\n/// @dev See Header.sol: (uint8,uint32,uint32,uint32,uint32): 1+4+4+4+4\nuint256 constant HEADER_LENGTH = 17;\n/// @dev See Request.sol: (uint96,uint64,uint32): 12+8+4\nuint256 constant REQUEST_LENGTH = 24;\n/// @dev See Tips.sol: (uint64,uint64,uint64,uint64): 8+8+8+8\nuint256 constant TIPS_LENGTH = 32;\n/// @dev The amount of discarded last bits when encoding tip values\nuint256 constant TIPS_GRANULARITY = 32;\n/// @dev Tip values could be only the multiples of TIPS_MULTIPLIER\nuint256 constant TIPS_MULTIPLIER = 1 \u003c\u003c TIPS_GRANULARITY;\n// ══════════════════════════════ STATEMENT SALTS ══════════════════════════════\n/// @dev Salts for signing various statements\nbytes32 constant ATTESTATION_VALID_SALT = keccak256(\"ATTESTATION_VALID_SALT\");\nbytes32 constant ATTESTATION_INVALID_SALT = keccak256(\"ATTESTATION_INVALID_SALT\");\nbytes32 constant RECEIPT_VALID_SALT = keccak256(\"RECEIPT_VALID_SALT\");\nbytes32 constant RECEIPT_INVALID_SALT = keccak256(\"RECEIPT_INVALID_SALT\");\nbytes32 constant SNAPSHOT_VALID_SALT = keccak256(\"SNAPSHOT_VALID_SALT\");\nbytes32 constant STATE_INVALID_SALT = keccak256(\"STATE_INVALID_SALT\");\n// ═════════════════════════════════ PROTOCOL ══════════════════════════════════\n/// @dev Optimistic period for new agent roots in LightManager\nuint32 constant AGENT_ROOT_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Timeout between the agent root could be proposed and resolved in LightManager\nuint32 constant AGENT_ROOT_PROPOSAL_TIMEOUT = 12 hours;\nuint32 constant BONDING_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Amount of time that the Notary will not be considered active after they won a dispute\nuint32 constant DISPUTE_TIMEOUT_NOTARY = 12 hours;\n/// @dev Amount of time without fresh data from Notaries before contract owner can resolve stuck disputes manually\nuint256 constant FRESH_DATA_TIMEOUT = 4 hours;\n/// @dev Maximum bytes per message = 2 KiB (somewhat arbitrarily set to begin)\nuint256 constant MAX_CONTENT_BYTES = 2 * 2 ** 10;\n/// @dev Maximum value for the summit tip that could be set in GasOracle\nuint256 constant MAX_SUMMIT_TIP = 0.01 ether;\n\n// contracts/libs/Errors.sol\n\n// ══════════════════════════════ INVALID CALLER ═══════════════════════════════\n\nerror CallerNotAgentManager();\nerror CallerNotDestination();\nerror CallerNotInbox();\nerror CallerNotSummit();\n\n// ══════════════════════════════ INCORRECT DATA ═══════════════════════════════\n\nerror IncorrectAttestation();\nerror IncorrectAgentDomain();\nerror IncorrectAgentIndex();\nerror IncorrectAgentProof();\nerror IncorrectAgentRoot();\nerror IncorrectDataHash();\nerror IncorrectDestinationDomain();\nerror IncorrectOriginDomain();\nerror IncorrectSnapshotProof();\nerror IncorrectSnapshotRoot();\nerror IncorrectState();\nerror IncorrectStatesAmount();\nerror IncorrectTipsProof();\nerror IncorrectVersionLength();\n\nerror IncorrectNonce();\nerror IncorrectSender();\nerror IncorrectRecipient();\n\nerror FlagOutOfRange();\nerror IndexOutOfRange();\nerror NonceOutOfRange();\n\nerror OutdatedNonce();\n\nerror UnformattedAttestation();\nerror UnformattedAttestationReport();\nerror UnformattedBaseMessage();\nerror UnformattedCallData();\nerror UnformattedCallDataPrefix();\nerror UnformattedMessage();\nerror UnformattedReceipt();\nerror UnformattedReceiptReport();\nerror UnformattedSignature();\nerror UnformattedSnapshot();\nerror UnformattedState();\nerror UnformattedStateReport();\n\n// ═══════════════════════════════ MERKLE TREES ════════════════════════════════\n\nerror LeafNotProven();\nerror MerkleTreeFull();\nerror NotEnoughLeafs();\nerror TreeHeightTooLow();\n\n// ═════════════════════════════ OPTIMISTIC PERIOD ═════════════════════════════\n\nerror BaseClientOptimisticPeriod();\nerror MessageOptimisticPeriod();\nerror SlashAgentOptimisticPeriod();\nerror WithdrawTipsOptimisticPeriod();\nerror ZeroProofMaturity();\n\n// ═══════════════════════════════ AGENT MANAGER ═══════════════════════════════\n\nerror AgentNotGuard();\nerror AgentNotNotary();\n\nerror AgentCantBeAdded();\nerror AgentNotActive();\nerror AgentNotActiveNorUnstaking();\nerror AgentNotFraudulent();\nerror AgentNotUnstaking();\nerror AgentUnknown();\n\nerror AgentRootNotProposed();\nerror AgentRootTimeoutNotOver();\n\nerror NotStuck();\n\nerror DisputeAlreadyResolved();\nerror DisputeNotOpened();\nerror DisputeTimeoutNotOver();\nerror GuardInDispute();\nerror NotaryInDispute();\n\nerror MustBeSynapseDomain();\nerror SynapseDomainForbidden();\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\nerror AlreadyExecuted();\nerror AlreadyFailed();\nerror DuplicatedSnapshotRoot();\nerror IncorrectMagicValue();\nerror GasLimitTooLow();\nerror GasSuppliedTooLow();\n\n// ══════════════════════════════════ ORIGIN ═══════════════════════════════════\n\nerror ContentLengthTooBig();\nerror EthTransferFailed();\nerror InsufficientEthBalance();\n\n// ════════════════════════════════ GAS ORACLE ═════════════════════════════════\n\nerror LocalGasDataNotSet();\nerror RemoteGasDataNotSet();\n\n// ═══════════════════════════════════ TIPS ════════════════════════════════════\n\nerror SummitTipTooHigh();\nerror TipsClaimMoreThanEarned();\nerror TipsClaimZero();\nerror TipsOverflow();\nerror TipsValueTooLow();\n\n// ════════════════════════════════ MEMORY VIEW ════════════════════════════════\n\nerror IndexedTooMuch();\nerror ViewOverrun();\nerror OccupiedMemory();\nerror UnallocatedMemory();\nerror PrecompileOutOfGas();\n\n// ═════════════════════════════════ MULTICALL ═════════════════════════════════\n\nerror MulticallFailed();\n\n// contracts/libs/TypeCasts.sol\n\nlibrary TypeCasts {\n    // alignment preserving cast\n    function addressToBytes32(address addr) internal pure returns (bytes32) {\n        return bytes32(uint256(uint160(addr)));\n    }\n\n    // alignment preserving cast\n    function bytes32ToAddress(bytes32 buf) internal pure returns (address) {\n        return address(uint160(uint256(buf)));\n    }\n}\n\n// contracts/libs/stack/Number.sol\n\n/// Number is a compact representation of uint256, that is fit into 16 bits\n/// with the maximum relative error under 0.4%.\ntype Number is uint16;\n\nusing NumberLib for Number global;\n\n/// # Number\n/// Library for compact representation of uint256 numbers.\n/// - Number is stored using mantissa and exponent, each occupying 8 bits.\n/// - Numbers under 2**8 are stored as `mantissa` with `exponent = 0xFF`.\n/// - Numbers at least 2**8 are approximated as `(256 + mantissa) \u003c\u003c exponent`\n/// \u003e - `0 \u003c= mantissa \u003c 256`\n/// \u003e - `0 \u003c= exponent \u003c= 247` (`256 * 2**248` doesn't fit into uint256)\n/// # Number stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type  | Bytes |\n/// | ---------- | -------- | ----- | ----- |\n/// | (002..001] | mantissa | uint8 | 1     |\n/// | (001..000] | exponent | uint8 | 1     |\n\nlibrary NumberLib {\n    /// @dev Amount of bits to shift to mantissa field\n    uint16 private constant SHIFT_MANTISSA = 8;\n\n    /// @notice For bwad math (binary wad) we use 2**64 as \"wad\" unit.\n    /// @dev We are using not using 10**18 as wad, because it is not stored precisely in NumberLib.\n    uint256 internal constant BWAD_SHIFT = 64;\n    uint256 internal constant BWAD = 1 \u003c\u003c BWAD_SHIFT;\n    /// @notice ~0.1% in bwad units.\n    uint256 internal constant PER_MILLE_SHIFT = BWAD_SHIFT - 10;\n    uint256 internal constant PER_MILLE = 1 \u003c\u003c PER_MILLE_SHIFT;\n\n    /// @notice Compresses uint256 number into 16 bits.\n    function compress(uint256 value) internal pure returns (Number) {\n        // Find `msb` such as `2**msb \u003c= value \u003c 2**(msb + 1)`\n        uint256 msb = mostSignificantBit(value);\n        // We want to preserve 9 bits of precision.\n        // The highest bit is always 1, so we can skip it.\n        // The remaining 8 highest bits are stored as mantissa.\n        if (msb \u003c 8) {\n            // Value is less than 2**8, so we can use value as mantissa with \"-1\" exponent.\n            return _encode(uint8(value), 0xFF);\n        } else {\n            // We use `msb - 8` as exponent otherwise. Note that `exponent \u003e= 0`.\n            unchecked {\n                uint256 exponent = msb - 8;\n                // Shifting right by `msb-8` bits will shift the \"remaining 8 highest bits\" into the 8 lowest bits.\n                // uint8() will truncate the highest bit.\n                return _encode(uint8(value \u003e\u003e exponent), uint8(exponent));\n            }\n        }\n    }\n\n    /// @notice Decompresses 16 bits number into uint256.\n    /// @dev The outcome is an approximation of the original number: `(value - value / 256) \u003c number \u003c= value`.\n    function decompress(Number number) internal pure returns (uint256 value) {\n        // Isolate 8 highest bits as the mantissa.\n        uint256 mantissa = Number.unwrap(number) \u003e\u003e SHIFT_MANTISSA;\n        // This will truncate the highest bits, leaving only the exponent.\n        uint256 exponent = uint8(Number.unwrap(number));\n        if (exponent == 0xFF) {\n            return mantissa;\n        } else {\n            unchecked {\n                return (256 + mantissa) \u003c\u003c (exponent);\n            }\n        }\n    }\n\n    /// @dev Returns the most significant bit of `x`\n    /// https://solidity-by-example.org/bitwise/\n    function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\n        // To find `msb` we determine it bit by bit, starting from the highest one.\n        // `0 \u003c= msb \u003c= 255`, so we start from the highest bit, 1\u003c\u003c7 == 128.\n        // If `x` is at least 2**128, then the highest bit of `x` is at least 128.\n        // solhint-disable no-inline-assembly\n        assembly {\n            // `f` is set to 1\u003c\u003c7 if `x \u003e= 2**128` and to 0 otherwise.\n            let f := shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\n            // If `x \u003e= 2**128` then set `msb` highest bit to 1 and shift `x` right by 128.\n            // Otherwise, `msb` remains 0 and `x` remains unchanged.\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        // `x` is now at most 2**128 - 1. Continue the same way, the next highest bit is 1\u003c\u003c6 == 64.\n        assembly {\n            // `f` is set to 1\u003c\u003c6 if `x \u003e= 2**64` and to 0 otherwise.\n            let f := shl(6, gt(x, 0xFFFFFFFFFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c5 if `x \u003e= 2**32` and to 0 otherwise.\n            let f := shl(5, gt(x, 0xFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c4 if `x \u003e= 2**16` and to 0 otherwise.\n            let f := shl(4, gt(x, 0xFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c3 if `x \u003e= 2**8` and to 0 otherwise.\n            let f := shl(3, gt(x, 0xFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c2 if `x \u003e= 2**4` and to 0 otherwise.\n            let f := shl(2, gt(x, 0xF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c1 if `x \u003e= 2**2` and to 0 otherwise.\n            let f := shl(1, gt(x, 0x3))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1 if `x \u003e= 2**1` and to 0 otherwise.\n            let f := gt(x, 0x1)\n            msb := or(msb, f)\n        }\n    }\n\n    /// @dev Wraps (mantissa, exponent) pair into Number.\n    function _encode(uint8 mantissa, uint8 exponent) private pure returns (Number) {\n        // Casts below are upcasts, so they are safe.\n        return Number.wrap(uint16(mantissa) \u003c\u003c SHIFT_MANTISSA | uint16(exponent));\n    }\n}\n\n// contracts/libs/stack/Request.sol\n\n/// Request is encoded data with \"message execution request\".\ntype Request is uint192;\n\nusing RequestLib for Request global;\n\n/// Library for formatting _the request part_ of _the base messages_.\n/// - Request represents a message sender requirements for the message execution on the destination chain.\n/// - Request occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n/// \u003e gasDrop field is included for future compatibility and is ignored at the moment.\n///\n/// # Request stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type   | Bytes | Description                                          |\n/// | ---------- | -------- | ------ | ----- | ---------------------------------------------------- |\n/// | (024..012] | gasDrop  | uint96 | 12    | Minimum amount of gas token to drop to the recipient |\n/// | (012..004] | gasLimit | uint64 | 8     | Minimum amount of gas units to supply for execution  |\n/// | (004..000] | version  | uint32 | 4     | Base message version to pass to the recipient        |\n\nlibrary RequestLib {\n    /// @dev Amount of bits to shift to gasDrop field\n    uint192 private constant SHIFT_GAS_DROP = 12 * 8;\n    /// @dev Amount of bits to shift to gasLimit field\n    uint192 private constant SHIFT_GAS_LIMIT = 4 * 8;\n\n    /// @notice Returns an encoded request with the given fields\n    /// @param gasDrop_     Minimum amount of gas token to drop to the recipient (ignored at the moment)\n    /// @param gasLimit_    Minimum amount of gas units to supply for execution\n    /// @param version_     Base message version to pass to the recipient\n    function encodeRequest(uint96 gasDrop_, uint64 gasLimit_, uint32 version_) internal pure returns (Request) {\n        // Casts below are upcasts, so they are safe\n        return Request.wrap(uint192(gasDrop_) \u003c\u003c SHIFT_GAS_DROP | uint192(gasLimit_) \u003c\u003c SHIFT_GAS_LIMIT | version_);\n    }\n\n    /// @notice Wraps the padded encoded request into a Request-typed value.\n    /// @dev The \"padded\" request is simply an encoded request casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded requests\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedRequest) internal pure returns (Request) {\n        // Casting to uint192 will truncate the highest bits, which is the behavior we want\n        return Request.wrap(uint192(paddedRequest));\n    }\n\n    /// @notice Returns the requested of gas token to drop to the recipient.\n    function gasDrop(Request request) internal pure returns (uint96) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return uint96(Request.unwrap(request) \u003e\u003e SHIFT_GAS_DROP);\n    }\n\n    /// @notice Returns the requested minimum amount of gas units to supply for execution.\n    function gasLimit(Request request) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Request.unwrap(request) \u003e\u003e SHIFT_GAS_LIMIT);\n    }\n\n    /// @notice Returns the requested base message version to pass to the recipient.\n    function version(Request request) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Request.unwrap(request));\n    }\n}\n\n// node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        require(value \u003c= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        require(value \u003c= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        require(value \u003c= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value \u003c= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        require(value \u003c= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        require(value \u003c= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        require(value \u003c= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        require(value \u003c= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        require(value \u003c= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        require(value \u003c= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        require(value \u003c= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        require(value \u003c= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        require(value \u003c= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        require(value \u003c= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        require(value \u003c= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value \u003c= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        require(value \u003c= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        require(value \u003c= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        require(value \u003c= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value \u003c= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        require(value \u003c= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        require(value \u003c= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        require(value \u003c= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value \u003c= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        require(value \u003c= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        require(value \u003c= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        require(value \u003c= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value \u003c= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        require(value \u003c= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value \u003c= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value \u003c= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     *\n     * _Available since v3.0._\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value \u003e= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     *\n     * _Available since v3.0._\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value \u003c= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     *\n     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length \u003e 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance \u003e= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance \u003e= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length \u003e 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n\n// contracts/base/MultiCallable.sol\n\n/// @notice Collection of Multicall utilities. Fork of Multicall3:\n/// https://github.com/mds1/multicall/blob/master/src/Multicall3.sol\nabstract contract MultiCallable {\n    struct Call {\n        bool allowFailure;\n        bytes callData;\n    }\n\n    struct Result {\n        bool success;\n        bytes returnData;\n    }\n\n    /// @notice Aggregates a few calls to this contract into one multicall without modifying `msg.sender`.\n    function multicall(Call[] calldata calls) external returns (Result[] memory callResults) {\n        uint256 amount = calls.length;\n        callResults = new Result[](amount);\n        Call calldata call_;\n        for (uint256 i = 0; i \u003c amount;) {\n            call_ = calls[i];\n            Result memory result = callResults[i];\n            // We perform a delegate call to ourselves here. Delegate call does not modify `msg.sender`, so\n            // this will have the same effect as if `msg.sender` performed all the calls themselves one by one.\n            // solhint-disable-next-line avoid-low-level-calls\n            (result.success, result.returnData) = address(this).delegatecall(call_.callData);\n            // solhint-disable-next-line no-inline-assembly\n            assembly {\n                // Revert if the call fails and failure is not allowed\n                // `allowFailure := calldataload(call_)` and `success := mload(result)`\n                if iszero(or(calldataload(call_), mload(result))) {\n                    // Revert with `0x4d6a2328` (function selector for `MulticallFailed()`)\n                    mstore(0x00, 0x4d6a232800000000000000000000000000000000000000000000000000000000)\n                    revert(0x00, 0x04)\n                }\n            }\n            unchecked {\n                ++i;\n            }\n        }\n    }\n}\n\n// contracts/base/Version.sol\n\n/**\n * @title Versioned\n * @notice Version getter for contracts. Doesn't use any storage slots, meaning\n * it will never cause any troubles with the upgradeable contracts. For instance, this contract\n * can be added or removed from the inheritance chain without shifting the storage layout.\n */\nabstract contract Versioned {\n    /**\n     * @notice Struct that is mimicking the storage layout of a string with 32 bytes or less.\n     * Length is limited by 32, so the whole string payload takes two memory words:\n     * @param length    String length\n     * @param data      String characters\n     */\n    struct _ShortString {\n        uint256 length;\n        bytes32 data;\n    }\n\n    /// @dev Length of the \"version string\"\n    uint256 private immutable _length;\n    /// @dev Bytes representation of the \"version string\".\n    /// Strings with length over 32 are not supported!\n    bytes32 private immutable _data;\n\n    constructor(string memory version_) {\n        _length = bytes(version_).length;\n        if (_length \u003e 32) revert IncorrectVersionLength();\n        // bytes32 is left-aligned =\u003e this will store the byte representation of the string\n        // with the trailing zeroes to complete the 32-byte word\n        _data = bytes32(bytes(version_));\n    }\n\n    function version() external view returns (string memory versionString) {\n        // Load the immutable values to form the version string\n        _ShortString memory str = _ShortString(_length, _data);\n        // The only way to do this cast is doing some dirty assembly\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            versionString := str\n        }\n    }\n}\n\n// contracts/libs/ChainContext.sol\n\n/// @notice Library for accessing chain context variables as tightly packed integers.\n/// Messaging contracts should rely on this library for accessing chain context variables\n/// instead of doing the casting themselves.\nlibrary ChainContext {\n    using SafeCast for uint256;\n\n    /// @notice Returns the current block number as uint40.\n    /// @dev Reverts if block number is greater than 40 bits, which is not supposed to happen\n    /// until the block.timestamp overflows (assuming block time is at least 1 second).\n    function blockNumber() internal view returns (uint40) {\n        return block.number.toUint40();\n    }\n\n    /// @notice Returns the current block timestamp as uint40.\n    /// @dev Reverts if block timestamp is greater than 40 bits, which is\n    /// supposed to happen approximately in year 36835.\n    function blockTimestamp() internal view returns (uint40) {\n        return block.timestamp.toUint40();\n    }\n\n    /// @notice Returns the chain id as uint32.\n    /// @dev Reverts if chain id is greater than 32 bits, which is not\n    /// supposed to happen in production.\n    function chainId() internal view returns (uint32) {\n        return block.chainid.toUint32();\n    }\n}\n\n// contracts/libs/Structures.sol\n\n// Here we define common enums and structures to enable their easier reusing later.\n\n// ═══════════════════════════════ AGENT STATUS ════════════════════════════════\n\n/// @dev Potential statuses for the off-chain bonded agent:\n/// - Unknown: never provided a bond =\u003e signature not valid\n/// - Active: has a bond in BondingManager =\u003e signature valid\n/// - Unstaking: has a bond in BondingManager, initiated the unstaking =\u003e signature not valid\n/// - Resting: used to have a bond in BondingManager, successfully unstaked =\u003e signature not valid\n/// - Fraudulent: proven to commit fraud, value in Merkle Tree not updated =\u003e signature not valid\n/// - Slashed: proven to commit fraud, value in Merkle Tree was updated =\u003e signature not valid\n/// Unstaked agent could later be added back to THE SAME domain by staking a bond again.\n/// Honest agent: Unknown -\u003e Active -\u003e unstaking -\u003e Resting -\u003e Active ...\n/// Malicious agent: Unknown -\u003e Active -\u003e Fraudulent -\u003e Slashed\n/// Malicious agent: Unknown -\u003e Active -\u003e Unstaking -\u003e Fraudulent -\u003e Slashed\nenum AgentFlag {\n    Unknown,\n    Active,\n    Unstaking,\n    Resting,\n    Fraudulent,\n    Slashed\n}\n\n/// @notice Struct for storing an agent in the BondingManager contract.\nstruct AgentStatus {\n    AgentFlag flag;\n    uint32 domain;\n    uint32 index;\n}\n// 184 bits available for tight packing\n\nusing StructureUtils for AgentStatus global;\n\n/// @notice Potential statuses of an agent in terms of being in dispute\n/// - None: agent is not in dispute\n/// - Pending: agent is in unresolved dispute\n/// - Slashed: agent was in dispute that lead to agent being slashed\n/// Note: agent who won the dispute has their status reset to None\nenum DisputeFlag {\n    None,\n    Pending,\n    Slashed\n}\n\n/// @notice Struct for storing dispute status of an agent.\n/// @param flag         Dispute flag: None/Pending/Slashed.\n/// @param openedAt     Timestamp when the latest agent dispute was opened (zero if not opened).\n/// @param resolvedAt   Timestamp when the latest agent dispute was resolved (zero if not resolved).\nstruct DisputeStatus {\n    DisputeFlag flag;\n    uint40 openedAt;\n    uint40 resolvedAt;\n}\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\n/// @notice Struct representing the status of Destination contract.\n/// @param snapRootTime     Timestamp when latest snapshot root was accepted\n/// @param agentRootTime    Timestamp when latest agent root was accepted\n/// @param notaryIndex      Index of Notary who signed the latest agent root\nstruct DestinationStatus {\n    uint40 snapRootTime;\n    uint40 agentRootTime;\n    uint32 notaryIndex;\n}\n\n// ═══════════════════════════════ EXECUTION HUB ═══════════════════════════════\n\n/// @notice Potential statuses of the message in Execution Hub.\n/// - None: there hasn't been a valid attempt to execute the message yet\n/// - Failed: there was a valid attempt to execute the message, but recipient reverted\n/// - Success: there was a valid attempt to execute the message, and recipient did not revert\n/// Note: message can be executed until its status is Success\nenum MessageStatus {\n    None,\n    Failed,\n    Success\n}\n\nlibrary StructureUtils {\n    /// @notice Checks that Agent is Active\n    function verifyActive(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active) {\n            revert AgentNotActive();\n        }\n    }\n\n    /// @notice Checks that Agent is Unstaking\n    function verifyUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Unstaking) {\n            revert AgentNotUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Active or Unstaking\n    function verifyActiveUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active \u0026\u0026 status.flag != AgentFlag.Unstaking) {\n            revert AgentNotActiveNorUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Fraudulent\n    function verifyFraudulent(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Fraudulent) {\n            revert AgentNotFraudulent();\n        }\n    }\n\n    /// @notice Checks that Agent is not Unknown\n    function verifyKnown(AgentStatus memory status) internal pure {\n        if (status.flag == AgentFlag.Unknown) {\n            revert AgentUnknown();\n        }\n    }\n}\n\n// contracts/libs/memory/MemView.sol\n\n/// @dev MemView is an untyped view over a portion of memory to be used instead of `bytes memory`\ntype MemView is uint256;\n\n/// @dev Attach library functions to MemView\nusing MemViewLib for MemView global;\n\n/// @notice Library for operations with the memory views.\n/// Forked from https://github.com/summa-tx/memview-sol with several breaking changes:\n/// - The codebase is ported to Solidity 0.8\n/// - Custom errors are added\n/// - The runtime type checking is replaced with compile-time check provided by User-Defined Value Types\n///   https://docs.soliditylang.org/en/latest/types.html#user-defined-value-types\n/// - uint256 is used as the underlying type for the \"memory view\" instead of bytes29.\n///   It is wrapped into MemView custom type in order not to be confused with actual integers.\n/// - Therefore the \"type\" field is discarded, allowing to allocate 16 bytes for both view location and length\n/// - The documentation is expanded\n/// - Library functions unused by the rest of the codebase are removed\n//  - Very pretty code separators are added :)\nlibrary MemViewLib {\n    /// @notice Stack layout for uint256 (from highest bits to lowest)\n    /// (32 .. 16]      loc     16 bytes    Memory address of underlying bytes\n    /// (16 .. 00]      len     16 bytes    Length of underlying bytes\n\n    // ═══════════════════════════════════════════ BUILDING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Instantiate a new untyped memory view. This should generally not be called directly.\n     * Prefer `ref` wherever possible.\n     * @param loc_          The memory address\n     * @param len_          The length\n     * @return The new view with the specified location and length\n     */\n    function build(uint256 loc_, uint256 len_) internal pure returns (MemView) {\n        uint256 end_ = loc_ + len_;\n        // Make sure that a view is not constructed that points to unallocated memory\n        // as this could be indicative of a buffer overflow attack\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            if gt(end_, mload(0x40)) { end_ := 0 }\n        }\n        if (end_ == 0) {\n            revert UnallocatedMemory();\n        }\n        return _unsafeBuildUnchecked(loc_, len_);\n    }\n\n    /**\n     * @notice Instantiate a memory view from a byte array.\n     * @dev Note that due to Solidity memory representation, it is not possible to\n     * implement a deref, as the `bytes` type stores its len in memory.\n     * @param arr           The byte array\n     * @return The memory view over the provided byte array\n     */\n    function ref(bytes memory arr) internal pure returns (MemView) {\n        uint256 len_ = arr.length;\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 loc_;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // We add 0x20, so that the view starts exactly where the array data starts\n            loc_ := add(arr, 0x20)\n        }\n        return build(loc_, len_);\n    }\n\n    // ════════════════════════════════════════════ CLONING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to the new memory.\n     * @param memView       The memory view\n     * @return arr          The cloned byte array\n     */\n    function clone(MemView memView) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        unchecked {\n            _unsafeCopyTo(memView, ptr + 0x20);\n        }\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 len_ = memView.len();\n        uint256 footprint_ = memView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    /**\n     * @notice Copies all views, joins them into a new bytearray.\n     * @param memViews      The memory views\n     * @return arr          The new byte array with joined data behind the given views\n     */\n    function join(MemView[] memory memViews) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        MemView newView;\n        unchecked {\n            newView = _unsafeJoin(memViews, ptr + 0x20);\n        }\n        uint256 len_ = newView.len();\n        uint256 footprint_ = newView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    // ══════════════════════════════════════════ INSPECTING MEMORY VIEW ═══════════════════════════════════════════════\n\n    /**\n     * @notice Returns the memory address of the underlying bytes.\n     * @param memView       The memory view\n     * @return loc_         The memory address\n     */\n    function loc(MemView memView) internal pure returns (uint256 loc_) {\n        // loc is stored in the highest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u003e\u003e 128;\n    }\n\n    /**\n     * @notice Returns the number of bytes of the view.\n     * @param memView       The memory view\n     * @return len_         The length of the view\n     */\n    function len(MemView memView) internal pure returns (uint256 len_) {\n        // len is stored in the lowest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u0026 type(uint128).max;\n    }\n\n    /**\n     * @notice Returns the endpoint of `memView`.\n     * @param memView       The memory view\n     * @return end_         The endpoint of `memView`\n     */\n    function end(MemView memView) internal pure returns (uint256 end_) {\n        // The endpoint never overflows uint128, let alone uint256, so we could use unchecked math here\n        unchecked {\n            return memView.loc() + memView.len();\n        }\n    }\n\n    /**\n     * @notice Returns the number of memory words this memory view occupies, rounded up.\n     * @param memView       The memory view\n     * @return words_       The number of memory words\n     */\n    function words(MemView memView) internal pure returns (uint256 words_) {\n        // returning ceil(length / 32.0)\n        unchecked {\n            return (memView.len() + 31) \u003e\u003e 5;\n        }\n    }\n\n    /**\n     * @notice Returns the in-memory footprint of a fresh copy of the view.\n     * @param memView       The memory view\n     * @return footprint_   The in-memory footprint of a fresh copy of the view.\n     */\n    function footprint(MemView memView) internal pure returns (uint256 footprint_) {\n        // words() * 32\n        return memView.words() \u003c\u003c 5;\n    }\n\n    // ════════════════════════════════════════════ HASHING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the keccak256 hash of the underlying memory\n     * @param memView       The memory view\n     * @return digest       The keccak256 hash of the underlying memory\n     */\n    function keccak(MemView memView) internal pure returns (bytes32 digest) {\n        uint256 loc_ = memView.loc();\n        uint256 len_ = memView.len();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            digest := keccak256(loc_, len_)\n        }\n    }\n\n    /**\n     * @notice Adds a salt to the keccak256 hash of the underlying data and returns the keccak256 hash of the\n     * resulting data.\n     * @param memView       The memory view\n     * @return digestSalted keccak256(salt, keccak256(memView))\n     */\n    function keccakSalted(MemView memView, bytes32 salt) internal pure returns (bytes32 digestSalted) {\n        return keccak256(bytes.concat(salt, memView.keccak()));\n    }\n\n    // ════════════════════════════════════════════ SLICING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Safe slicing without memory modification.\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the given index\n     */\n    function slice(MemView memView, uint256 index_, uint256 len_) internal pure returns (MemView) {\n        uint256 loc_ = memView.loc();\n        // Ensure it doesn't overrun the view\n        if (loc_ + index_ + len_ \u003e memView.end()) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // loc_ + index_ \u003c= memView.end()\n            return build({loc_: loc_ + index_, len_: len_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing bytes from `index` to end(memView).\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @return The new view for the slice starting from the given index until the initial view endpoint\n     */\n    function sliceFrom(MemView memView, uint256 index_) internal pure returns (MemView) {\n        uint256 len_ = memView.len();\n        // Ensure it doesn't overrun the view\n        if (index_ \u003e len_) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // index_ \u003c= len_ =\u003e memView.loc() + index_ \u003c= memView.loc() + memView.len() == memView.end()\n            return build({loc_: memView.loc() + index_, len_: len_ - index_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the first `len` bytes.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the initial view beginning\n     */\n    function prefix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        return memView.slice({index_: 0, len_: len_});\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the last `len` byte.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length until the initial view endpoint\n     */\n    function postfix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        uint256 viewLen = memView.len();\n        // Ensure it doesn't overrun the view\n        if (len_ \u003e viewLen) {\n            revert ViewOverrun();\n        }\n        // Could do the unchecked math due to the check above\n        uint256 index_;\n        unchecked {\n            index_ = viewLen - len_;\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // len_ \u003c= memView.len() =\u003e memView.loc() \u003c= loc_ \u003c= memView.end()\n            return build({loc_: memView.loc() + viewLen - len_, len_: len_});\n        }\n    }\n\n    // ═══════════════════════════════════════════ INDEXING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Load up to 32 bytes from the view onto the stack.\n     * @dev Returns a bytes32 with only the `bytes_` HIGHEST bytes set.\n     * This can be immediately cast to a smaller fixed-length byte array.\n     * To automatically cast to an integer, use `indexUint`.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return result       The 32 byte result having only `bytes_` highest bytes set\n     */\n    function index(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (bytes32 result) {\n        if (bytes_ == 0) {\n            return bytes32(0);\n        }\n        // Can't load more than 32 bytes to the stack in one go\n        if (bytes_ \u003e 32) {\n            revert IndexedTooMuch();\n        }\n        // The last indexed byte should be within view boundaries\n        if (index_ + bytes_ \u003e memView.len()) {\n            revert ViewOverrun();\n        }\n        uint256 bitLength = bytes_ \u003c\u003c 3; // bytes_ * 8\n        uint256 loc_ = memView.loc();\n        // Get a mask with `bitLength` highest bits set\n        uint256 mask;\n        // 0x800...00 binary representation is 100...00\n        // sar stands for \"signed arithmetic shift\": https://en.wikipedia.org/wiki/Arithmetic_shift\n        // sar(N-1, 100...00) = 11...100..00, with exactly N highest bits set to 1\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            mask := sar(sub(bitLength, 1), 0x8000000000000000000000000000000000000000000000000000000000000000)\n        }\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load a full word using index offset, and apply mask to ignore non-relevant bytes\n            result := and(mload(add(loc_, index_)), mask)\n        }\n    }\n\n    /**\n     * @notice Parse an unsigned integer from the view at `index`.\n     * @dev Requires that the view have \u003e= `bytes_` bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return The unsigned integer\n     */\n    function indexUint(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (uint256) {\n        bytes32 indexedBytes = memView.index(index_, bytes_);\n        // `index()` returns left-aligned `bytes_`, while integers are right-aligned\n        // Shifting here to right-align with the full 32 bytes word: need to shift right `(32 - bytes_)` bytes\n        unchecked {\n            // memView.index() reverts when bytes_ \u003e 32, thus unchecked math\n            return uint256(indexedBytes) \u003e\u003e ((32 - bytes_) \u003c\u003c 3);\n        }\n    }\n\n    /**\n     * @notice Parse an address from the view at `index`.\n     * @dev Requires that the view have \u003e= 20 bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @return The address\n     */\n    function indexAddress(MemView memView, uint256 index_) internal pure returns (address) {\n        // index 20 bytes as `uint160`, and then cast to `address`\n        return address(uint160(memView.indexUint(index_, 20)));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns a memory view over the specified memory location\n    /// without checking if it points to unallocated memory.\n    function _unsafeBuildUnchecked(uint256 loc_, uint256 len_) private pure returns (MemView) {\n        // There is no scenario where loc or len would overflow uint128, so we omit this check.\n        // We use the highest 128 bits to encode the location and the lowest 128 bits to encode the length.\n        return MemView.wrap((loc_ \u003c\u003c 128) | len_);\n    }\n\n    /**\n     * @notice Copy the view to a location, return an unsafe memory reference\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memView       The memory view\n     * @param newLoc        The new location to copy the underlying view data\n     * @return The memory view over the unsafe memory with the copied underlying data\n     */\n    function _unsafeCopyTo(MemView memView, uint256 newLoc) private view returns (MemView) {\n        uint256 len_ = memView.len();\n        uint256 oldLoc = memView.loc();\n\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (newLoc \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        bool res;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // use the identity precompile (0x04) to copy\n            res := staticcall(gas(), 0x04, oldLoc, len_, newLoc, len_)\n        }\n        if (!res) revert PrecompileOutOfGas();\n        return _unsafeBuildUnchecked({loc_: newLoc, len_: len_});\n    }\n\n    /**\n     * @notice Join the views in memory, return an unsafe reference to the memory.\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memViews      The memory views\n     * @return The conjoined view pointing to the new memory\n     */\n    function _unsafeJoin(MemView[] memory memViews, uint256 location) private view returns (MemView) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (location \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        // Copy the views to the specified location one by one, by tracking the amount of copied bytes so far\n        uint256 offset = 0;\n        for (uint256 i = 0; i \u003c memViews.length;) {\n            MemView memView = memViews[i];\n            // We can use the unchecked math here as location + sum(view.length) will never overflow uint256\n            unchecked {\n                _unsafeCopyTo(memView, location + offset);\n                offset += memView.len();\n                ++i;\n            }\n        }\n        return _unsafeBuildUnchecked({loc_: location, len_: offset});\n    }\n}\n\n// contracts/libs/merkle/MerkleMath.sol\n\nlibrary MerkleMath {\n    // ═════════════════════════════════════════ BASIC MERKLE CALCULATIONS ═════════════════════════════════════════════\n\n    /**\n     * @notice Calculates the merkle root for the given leaf and merkle proof.\n     * @dev Will revert if proof length exceeds the tree height.\n     * @param index     Index of `leaf` in tree\n     * @param leaf      Leaf of the merkle tree\n     * @param proof     Proof of inclusion of `leaf` in the tree\n     * @param height    Height of the merkle tree\n     * @return root_    Calculated Merkle Root\n     */\n    function proofRoot(uint256 index, bytes32 leaf, bytes32[] memory proof, uint256 height)\n        internal\n        pure\n        returns (bytes32 root_)\n    {\n        // Proof length could not exceed the tree height\n        uint256 proofLen = proof.length;\n        if (proofLen \u003e height) revert TreeHeightTooLow();\n        root_ = leaf;\n        /// @dev Apply unchecked to all ++h operations\n        unchecked {\n            // Go up the tree levels from the leaf following the proof\n            for (uint256 h = 0; h \u003c proofLen; ++h) {\n                // Get a sibling node on current level: this is proof[h]\n                root_ = getParent(root_, proof[h], index, h);\n            }\n            // Go up to the root: the remaining siblings are EMPTY\n            for (uint256 h = proofLen; h \u003c height; ++h) {\n                root_ = getParent(root_, bytes32(0), index, h);\n            }\n        }\n    }\n\n    /**\n     * @notice Calculates the parent of a node on the path from one of the leafs to root.\n     * @param node          Node on a path from tree leaf to root\n     * @param sibling       Sibling for a given node\n     * @param leafIndex     Index of the tree leaf\n     * @param nodeHeight    \"Level height\" for `node` (ZERO for leafs, ORIGIN_TREE_HEIGHT for root)\n     */\n    function getParent(bytes32 node, bytes32 sibling, uint256 leafIndex, uint256 nodeHeight)\n        internal\n        pure\n        returns (bytes32 parent)\n    {\n        // Index for `node` on its \"tree level\" is (leafIndex / 2**height)\n        // \"Left child\" has even index, \"right child\" has odd index\n        if ((leafIndex \u003e\u003e nodeHeight) \u0026 1 == 0) {\n            // Left child\n            return getParent(node, sibling);\n        } else {\n            // Right child\n            return getParent(sibling, node);\n        }\n    }\n\n    /// @notice Calculates the parent of tow nodes in the merkle tree.\n    /// @dev We use implementation with H(0,0) = 0\n    /// This makes EVERY empty node in the tree equal to ZERO,\n    /// saving us from storing H(0,0), H(H(0,0), H(0, 0)), and so on\n    /// @param leftChild    Left child of the calculated node\n    /// @param rightChild   Right child of the calculated node\n    /// @return parent      Value for the node having above mentioned children\n    function getParent(bytes32 leftChild, bytes32 rightChild) internal pure returns (bytes32 parent) {\n        if (leftChild == bytes32(0) \u0026\u0026 rightChild == bytes32(0)) {\n            return 0;\n        } else {\n            return keccak256(bytes.concat(leftChild, rightChild));\n        }\n    }\n\n    // ════════════════════════════════ ROOT/PROOF CALCULATION FOR A LIST OF LEAFS ═════════════════════════════════════\n\n    /**\n     * @notice Calculates merkle root for a list of given leafs.\n     * Merkle Tree is constructed by padding the list with ZERO values for leafs until list length is `2**height`.\n     * Merkle Root is calculated for the constructed tree, and then saved in `leafs[0]`.\n     * \u003e Note:\n     * \u003e - `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * \u003e - Caller is expected not to reuse `hashes` list after the call, and only use `leafs[0]` value,\n     * which is guaranteed to contain the calculated merkle root.\n     * \u003e - root is calculated using the `H(0,0) = 0` Merkle Tree implementation. See MerkleTree.sol for details.\n     * @dev Amount of leaves should be at most `2**height`\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param height    Height of the Merkle Tree to construct\n     */\n    function calculateRoot(bytes32[] memory hashes, uint256 height) internal pure {\n        uint256 levelLength = hashes.length;\n        // Amount of hashes could not exceed amount of leafs in tree with the given height\n        if (levelLength \u003e (1 \u003c\u003c height)) revert TreeHeightTooLow();\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\": the amount of iterations for the for loop above.\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n            }\n        }\n    }\n\n    /**\n     * @notice Generates a proof of inclusion of a leaf in the list. If the requested index is outside\n     * of the list range, generates a proof of inclusion for an empty leaf (proof of non-inclusion).\n     * The Merkle Tree is constructed by padding the list with ZERO values until list length is a power of two\n     * __AND__ index is in the extended list range. For example:\n     *  - `hashes.length == 6` and `0 \u003c= index \u003c= 7` will \"extend\" the list to 8 entries.\n     *  - `hashes.length == 6` and `7 \u003c index \u003c= 15` will \"extend\" the list to 16 entries.\n     * \u003e Note: `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * Caller is expected not to reuse `hashes` list after the call.\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param index     Leaf index to generate the proof for\n     * @return proof    Generated merkle proof\n     */\n    function calculateProof(bytes32[] memory hashes, uint256 index) internal pure returns (bytes32[] memory proof) {\n        // Use only meaningful values for the shortened proof\n        // Check if index is within the list range (we want to generates proofs for outside leafs as well)\n        uint256 height = getHeight(index \u003c hashes.length ? hashes.length : (index + 1));\n        proof = new bytes32[](height);\n        uint256 levelLength = hashes.length;\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Use sibling for the merkle proof; `index^1` is index of our sibling\n                proof[h] = (index ^ 1 \u003c levelLength) ? hashes[index ^ 1] : bytes32(0);\n\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\"\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n                // Traverse to parent node\n                index \u003e\u003e= 1;\n            }\n        }\n    }\n\n    /// @notice Returns the height of the tree having a given amount of leafs.\n    function getHeight(uint256 leafs) internal pure returns (uint256 height) {\n        uint256 amount = 1;\n        while (amount \u003c leafs) {\n            unchecked {\n                ++height;\n            }\n            amount \u003c\u003c= 1;\n        }\n    }\n}\n\n// contracts/libs/stack/GasData.sol\n\n/// GasData in encoded data with \"basic information about gas prices\" for some chain.\ntype GasData is uint96;\n\nusing GasDataLib for GasData global;\n\n/// ChainGas is encoded data with given chain's \"basic information about gas prices\".\ntype ChainGas is uint128;\n\nusing GasDataLib for ChainGas global;\n\n/// Library for encoding and decoding GasData and ChainGas structs.\n/// # GasData\n/// `GasData` is a struct to store the \"basic information about gas prices\", that could\n/// be later used to approximate the cost of a message execution, and thus derive the\n/// minimal tip values for sending a message to the chain.\n/// \u003e - `GasData` is supposed to be cached by `GasOracle` contract, allowing to store the\n/// \u003e approximates instead of the exact values, and thus save on storage costs.\n/// \u003e - For instance, if `GasOracle` only updates the values on +- 10% change, having an\n/// \u003e 0.4% error on the approximates would be acceptable.\n/// `GasData` is supposed to be included in the Origin's state, which are synced across\n/// chains using Agent-signed snapshots and attestations.\n/// ## GasData stack layout (from highest bits to lowest)\n///\n/// | Position   | Field        | Type   | Bytes | Description                                         |\n/// | ---------- | ------------ | ------ | ----- | --------------------------------------------------- |\n/// | (012..010] | gasPrice     | uint16 | 2     | Gas price for the chain (in Wei per gas unit)       |\n/// | (010..008] | dataPrice    | uint16 | 2     | Calldata price (in Wei per byte of content)         |\n/// | (008..006] | execBuffer   | uint16 | 2     | Tx fee safety buffer for message execution (in Wei) |\n/// | (006..004] | amortAttCost | uint16 | 2     | Amortized cost for attestation submission (in Wei)  |\n/// | (004..002] | etherPrice   | uint16 | 2     | Chain's Ether Price / Mainnet Ether Price (in BWAD) |\n/// | (002..000] | markup       | uint16 | 2     | Markup for the message execution (in BWAD)          |\n/// \u003e See Number.sol for more details on `Number` type and BWAD (binary WAD) math.\n///\n/// ## ChainGas stack layout (from highest bits to lowest)\n///\n/// | Position   | Field   | Type   | Bytes | Description      |\n/// | ---------- | ------- | ------ | ----- | ---------------- |\n/// | (016..004] | gasData | uint96 | 12    | Chain's gas data |\n/// | (004..000] | domain  | uint32 | 4     | Chain's domain   |\nlibrary GasDataLib {\n    /// @dev Amount of bits to shift to gasPrice field\n    uint96 private constant SHIFT_GAS_PRICE = 10 * 8;\n    /// @dev Amount of bits to shift to dataPrice field\n    uint96 private constant SHIFT_DATA_PRICE = 8 * 8;\n    /// @dev Amount of bits to shift to execBuffer field\n    uint96 private constant SHIFT_EXEC_BUFFER = 6 * 8;\n    /// @dev Amount of bits to shift to amortAttCost field\n    uint96 private constant SHIFT_AMORT_ATT_COST = 4 * 8;\n    /// @dev Amount of bits to shift to etherPrice field\n    uint96 private constant SHIFT_ETHER_PRICE = 2 * 8;\n\n    /// @dev Amount of bits to shift to gasData field\n    uint128 private constant SHIFT_GAS_DATA = 4 * 8;\n\n    // ═════════════════════════════════════════════════ GAS DATA ══════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded GasData struct with the given fields.\n    /// @param gasPrice_        Gas price for the chain (in Wei per gas unit)\n    /// @param dataPrice_       Calldata price (in Wei per byte of content)\n    /// @param execBuffer_      Tx fee safety buffer for message execution (in Wei)\n    /// @param amortAttCost_    Amortized cost for attestation submission (in Wei)\n    /// @param etherPrice_      Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n    /// @param markup_          Markup for the message execution (in BWAD)\n    function encodeGasData(\n        Number gasPrice_,\n        Number dataPrice_,\n        Number execBuffer_,\n        Number amortAttCost_,\n        Number etherPrice_,\n        Number markup_\n    ) internal pure returns (GasData) {\n        // Number type wraps uint16, so could safely be casted to uint96\n        // forgefmt: disable-next-item\n        return GasData.wrap(\n            uint96(Number.unwrap(gasPrice_)) \u003c\u003c SHIFT_GAS_PRICE |\n            uint96(Number.unwrap(dataPrice_)) \u003c\u003c SHIFT_DATA_PRICE |\n            uint96(Number.unwrap(execBuffer_)) \u003c\u003c SHIFT_EXEC_BUFFER |\n            uint96(Number.unwrap(amortAttCost_)) \u003c\u003c SHIFT_AMORT_ATT_COST |\n            uint96(Number.unwrap(etherPrice_)) \u003c\u003c SHIFT_ETHER_PRICE |\n            uint96(Number.unwrap(markup_))\n        );\n    }\n\n    /// @notice Wraps padded uint256 value into GasData struct.\n    function wrapGasData(uint256 paddedGasData) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(paddedGasData));\n    }\n\n    /// @notice Returns the gas price, in Wei per gas unit.\n    function gasPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_GAS_PRICE));\n    }\n\n    /// @notice Returns the calldata price, in Wei per byte of content.\n    function dataPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_DATA_PRICE));\n    }\n\n    /// @notice Returns the tx fee safety buffer for message execution, in Wei.\n    function execBuffer(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_EXEC_BUFFER));\n    }\n\n    /// @notice Returns the amortized cost for attestation submission, in Wei.\n    function amortAttCost(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_AMORT_ATT_COST));\n    }\n\n    /// @notice Returns the ratio of Chain's Ether Price / Mainnet Ether Price, in BWAD math.\n    function etherPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_ETHER_PRICE));\n    }\n\n    /// @notice Returns the markup for the message execution, in BWAD math.\n    function markup(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data)));\n    }\n\n    // ════════════════════════════════════════════════ CHAIN DATA ═════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded ChainGas struct with the given fields.\n    /// @param gasData_ Chain's gas data\n    /// @param domain_  Chain's domain\n    function encodeChainGas(GasData gasData_, uint32 domain_) internal pure returns (ChainGas) {\n        // GasData type wraps uint96, so could safely be casted to uint128\n        return ChainGas.wrap(uint128(GasData.unwrap(gasData_)) \u003c\u003c SHIFT_GAS_DATA | uint128(domain_));\n    }\n\n    /// @notice Wraps padded uint256 value into ChainGas struct.\n    function wrapChainGas(uint256 paddedChainGas) internal pure returns (ChainGas) {\n        // Casting to uint128 will truncate the highest bits, which is the behavior we want\n        return ChainGas.wrap(uint128(paddedChainGas));\n    }\n\n    /// @notice Returns the chain's gas data.\n    function gasData(ChainGas data) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(ChainGas.unwrap(data) \u003e\u003e SHIFT_GAS_DATA));\n    }\n\n    /// @notice Returns the chain's domain.\n    function domain(ChainGas data) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(ChainGas.unwrap(data));\n    }\n\n    /// @notice Returns the hash for the list of ChainGas structs.\n    function snapGasHash(ChainGas[] memory snapGas) internal pure returns (bytes32 snapGasHash_) {\n        // Use assembly to calculate the hash of the array without copying it\n        // ChainGas takes a single word of storage, thus ChainGas[] is stored in the following way:\n        // 0x00: length of the array, in words\n        // 0x20: first ChainGas struct\n        // 0x40: second ChainGas struct\n        // And so on...\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Find the location where the array data starts, we add 0x20 to skip the length field\n            let loc := add(snapGas, 0x20)\n            // Load the length of the array (in words).\n            // Shifting left 5 bits is equivalent to multiplying by 32: this converts from words to bytes.\n            let len := shl(5, mload(snapGas))\n            // Calculate the hash of the array\n            snapGasHash_ := keccak256(loc, len)\n        }\n    }\n}\n\n// contracts/libs/stack/Header.sol\n\n/// Header is encoded data with \"general routing information\".\ntype Header is uint136;\n\nusing HeaderLib for Header global;\n\n/// Types of messages supported by Origin-Destination\n/// - Base: message sent by protocol user, contains tips\n/// - Manager: message sent between AgentManager contracts located on different chains, no tips\nenum MessageFlag {\n    Base,\n    Manager\n}\n\nusing HeaderLib for MessageFlag global;\n\n/// Library for formatting _the header part_ of _the messages used by Origin and Destination_.\n/// - Header represents general information for routing a Message for Origin and Destination.\n/// - Header occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n///\n/// # Header stack layout (from highest bits to lowest)\n///\n/// | Position   | Field            | Type   | Bytes | Description                             |\n/// | ---------- | ---------------- | ------ | ----- | --------------------------------------- |\n/// | (017..016] | flag             | uint8  | 1     | Flag specifying the type of message     |\n/// | (016..012] | origin           | uint32 | 4     | Domain where message originated         |\n/// | (012..008] | nonce            | uint32 | 4     | Message nonce on the origin domain      |\n/// | (008..004] | destination      | uint32 | 4     | Domain where message will be executed   |\n/// | (004..000] | optimisticPeriod | uint32 | 4     | Optimistic period that will be enforced |\nlibrary HeaderLib {\n    /// @dev Amount of bits to shift to flag field\n    uint136 private constant SHIFT_FLAG = 16 * 8;\n    /// @dev Amount of bits to shift to origin field\n    uint136 private constant SHIFT_ORIGIN = 12 * 8;\n    /// @dev Amount of bits to shift to nonce field\n    uint136 private constant SHIFT_NONCE = 8 * 8;\n    /// @dev Amount of bits to shift to destination field\n    uint136 private constant SHIFT_DESTINATION = 4 * 8;\n\n    /// @notice Returns an encoded header with provided fields\n    /// @param origin_              Domain of origin chain\n    /// @param nonce_               Message nonce on origin chain\n    /// @param destination_         Domain of destination chain\n    /// @param optimisticPeriod_    Optimistic period for message execution\n    function encodeHeader(\n        MessageFlag flag_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint32 destination_,\n        uint32 optimisticPeriod_\n    ) internal pure returns (Header) {\n        // All casts below are upcasts, so they are safe\n        // forgefmt: disable-next-item\n        return Header.wrap(\n            uint136(uint8(flag_)) \u003c\u003c SHIFT_FLAG |\n            uint136(origin_) \u003c\u003c SHIFT_ORIGIN |\n            uint136(nonce_) \u003c\u003c SHIFT_NONCE |\n            uint136(destination_) \u003c\u003c SHIFT_DESTINATION |\n            uint136(optimisticPeriod_)\n        );\n    }\n\n    /// @notice Checks that the header is a valid encoded header.\n    function isHeader(uint256 paddedHeader) internal pure returns (bool) {\n        // Check that flag is within range\n        return _flag(paddedHeader) \u003c= uint8(type(MessageFlag).max);\n    }\n\n    /// @notice Wraps the padded encoded request into a Header-typed value.\n    /// @dev The \"padded\" header is simply an encoded header casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded headers\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedHeader) internal pure returns (Header) {\n        // Check that flag is within range\n        if (!isHeader(paddedHeader)) revert FlagOutOfRange();\n        // Casting to uint136 will truncate the highest bits, which is the behavior we want\n        return Header.wrap(uint136(paddedHeader));\n    }\n\n    /// @notice Returns header's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Header header) internal pure returns (bytes32 hashedHeader) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store header in scratch space\n            mstore(0, header)\n            // Compute hash of header padded to 32 bytes\n            hashedHeader := keccak256(0, 32)\n        }\n    }\n\n    // ══════════════════════════════════════════════ HEADER SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns header's flag field\n    function flag(Header header) internal pure returns (MessageFlag) {\n        // We check that flag is within range when wrapping the header, so this cast is safe\n        return MessageFlag(_flag(Header.unwrap(header)));\n    }\n\n    /// @notice Returns header's origin field\n    function origin(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_ORIGIN);\n    }\n\n    /// @notice Returns header's nonce field\n    function nonce(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_NONCE);\n    }\n\n    /// @notice Returns header's destination field\n    function destination(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_DESTINATION);\n    }\n\n    /// @notice Returns header's optimistic seconds field\n    function optimisticPeriod(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns header's flag field without casting to MessageFlag\n    function _flag(uint256 paddedHeader) private pure returns (uint8) {\n        // Casting to uint8 will truncate the highest bits, which is the behavior we want\n        return uint8(paddedHeader \u003e\u003e SHIFT_FLAG);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n     * constructor.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall \u0026\u0026 _initialized \u003c 1) || (!AddressUpgradeable.isContract(address(this)) \u0026\u0026 _initialized == 1),\n            \"Initializable: contract is already initialized\"\n        );\n        _initialized = 1;\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: setting the version to 255 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing \u0026\u0026 _initialized \u003c version, \"Initializable: contract is already initialized\");\n        _initialized = version;\n        _initializing = true;\n        _;\n        _initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        require(_initializing, \"Initializable: contract is not initializing\");\n        _;\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized != type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint8) {\n        return _initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _initializing;\n    }\n}\n\n// contracts/interfaces/IAgentManager.sol\n\ninterface IAgentManager {\n    /**\n     * @notice Allows Inbox to open a Dispute between a Guard and a Notary, if they are both not in Dispute already.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Guard or Notary is already in Dispute.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Allows Inbox to slash an agent, if their fraud was proven.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Domain doesn't match the saved agent domain.\n     * @param domain    Domain where the Agent is active\n     * @param agent     Address of the Agent\n     * @param prover    Address that initially provided fraud proof\n     */\n    function slashAgent(uint32 domain, address agent, address prover) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest known root of the Agent Merkle Tree.\n     */\n    function agentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns the number of opened Disputes.\n     * @dev This includes the Disputes that have been resolved already.\n     */\n    function getDisputesAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns information about the dispute with the given index.\n     * @dev Will revert if dispute with given index hasn't been opened yet.\n     * @param index             Dispute index\n     * @return guard            Address of the Guard in the Dispute\n     * @return notary           Address of the Notary in the Dispute\n     * @return slashedAgent     Address of the Agent who was slashed when Dispute was resolved\n     * @return fraudProver      Address who provided fraud proof to resolve the Dispute\n     * @return reportPayload    Raw payload with report data that led to the Dispute\n     * @return reportSignature  Guard signature for the report payload\n     */\n    function getDispute(uint256 index)\n        external\n        view\n        returns (\n            address guard,\n            address notary,\n            address slashedAgent,\n            address fraudProver,\n            bytes memory reportPayload,\n            bytes memory reportSignature\n        );\n\n    /**\n     * @notice Returns the current Dispute status of a given agent. See Structures.sol for details.\n     * @dev Every returned value will be set to zero if agent was not slashed and is not in Dispute.\n     * `rival` and `disputePtr` will be set to zero if the agent was slashed without being in Dispute.\n     * @param agent         Agent address\n     * @return flag         Flag describing the current Dispute status for the agent: None/Pending/Slashed\n     * @return rival        Address of the rival agent in the Dispute\n     * @return fraudProver  Address who provided fraud proof to resolve the Dispute\n     * @return disputePtr   Index of the opened Dispute PLUS ONE. Zero if agent is not in Dispute.\n     */\n    function disputeStatus(address agent)\n        external\n        view\n        returns (DisputeFlag flag, address rival, address fraudProver, uint256 disputePtr);\n}\n\n// contracts/interfaces/IAgentSecured.sol\n\ninterface IAgentSecured {\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * between a Guard and a Notary has been opened.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * has been resolved due to one of the agents being slashed.\n     * \u003e `rivalIndex` will be ZERO, if the slashed agent was not in the Dispute.\n     * @param slashedIndex  Index of the slashed agent in the Agent Merkle Tree\n     * @param rivalIndex    Index of the their Dispute Rival in the Agent Merkle Tree\n     */\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the address of the local AgentManager contract, which is treated as\n     * the \"source of truth\" for agent statuses.\n     */\n    function agentManager() external view returns (address);\n\n    /**\n     * @notice Returns the address of the local Inbox contract, which is treated as\n     * the \"source of truth\" for agent-signed statements.\n     * @dev Inbox passes verified agent statements to `IAgentSecured` contract.\n     */\n    function inbox() external view returns (address);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns (flag, openedAt, resolvedAt) that describes the latest status of\n     * the latest dispute for an agent with a given index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param agentIndex    Agent index in the Agent Merkle Tree\n     * @return              Latest dispute status for the given agent: (flag, openedAt, resolvedAt)\n     */\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory);\n}\n\n// contracts/libs/memory/ByteString.sol\n\n/// @dev CallData is a memory view over the payload to be used for an external call, i.e.\n/// recipient.call(callData). Its length is always (4 + 32 * N) bytes:\n/// - First 4 bytes represent the function selector.\n/// - 32 * N bytes represent N words that function arguments occupy.\ntype CallData is uint256;\n\n/// @dev Attach library functions to CallData\nusing ByteString for CallData global;\n\n/// @dev Signature is a memory view over a \"65 bytes\" array representing a ECDSA signature.\ntype Signature is uint256;\n\n/// @dev Attach library functions to Signature\nusing ByteString for Signature global;\n\nlibrary ByteString {\n    using MemViewLib for bytes;\n\n    /**\n     * @dev non-compact ECDSA signatures are enforced as of OZ 4.7.3\n     *\n     *      Signature payload memory layout\n     * [000 .. 032) r   bytes32 32 bytes\n     * [032 .. 064) s   bytes32 32 bytes\n     * [064 .. 065) v   uint8    1 byte\n     */\n    uint256 internal constant SIGNATURE_LENGTH = 65;\n    uint256 private constant OFFSET_R = 0;\n    uint256 private constant OFFSET_S = 32;\n    uint256 private constant OFFSET_V = 64;\n\n    /**\n     * @dev Calldata memory layout\n     * [000 .. 004) selector    bytes4  4 bytes\n     *      Optional: N function arguments\n     * [004 .. 036) arg1        bytes32 32 bytes\n     *      ..\n     * [AAA .. END) argN        bytes32 32 bytes\n     */\n    uint256 internal constant SELECTOR_LENGTH = 4;\n    uint256 private constant OFFSET_SELECTOR = 0;\n    uint256 private constant OFFSET_ARGUMENTS = SELECTOR_LENGTH;\n\n    // ═════════════════════════════════════════════════ SIGNATURE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the signature payload from the given values.\n     * @dev Using ByteString.formatSignature({r: r, s: s, v: v}) will make sure\n     * that params are given in the right order.\n     */\n    function formatSignature(bytes32 r, bytes32 s, uint8 v) internal pure returns (bytes memory) {\n        return abi.encodePacked(r, s, v);\n    }\n\n    /**\n     * @notice Returns a Signature view over for the given payload.\n     * @dev Will revert if the payload is not a signature.\n     */\n    function castToSignature(bytes memory payload) internal pure returns (Signature) {\n        return castToSignature(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Signature view.\n     * @dev Will revert if the memory view is not over a signature.\n     */\n    function castToSignature(MemView memView) internal pure returns (Signature) {\n        if (!isSignature(memView)) revert UnformattedSignature();\n        return Signature.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a signature\n     */\n    function isSignature(MemView memView) internal pure returns (bool) {\n        return memView.len() == SIGNATURE_LENGTH;\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Signature signature) internal pure returns (MemView) {\n        return MemView.wrap(Signature.unwrap(signature));\n    }\n\n    // ═════════════════════════════════════════════ SIGNATURE SLICING ═════════════════════════════════════════════════\n\n    /// @notice Unpacks signature payload into (r, s, v) parameters.\n    /// @dev Make sure to verify signature length with isSignature() beforehand.\n    function toRSV(Signature signature) internal pure returns (bytes32 r, bytes32 s, uint8 v) {\n        // Get the underlying memory view\n        MemView memView = unwrap(signature);\n        r = memView.index({index_: OFFSET_R, bytes_: 32});\n        s = memView.index({index_: OFFSET_S, bytes_: 32});\n        // Can be safely casted to uint8, since we index a single byte\n        v = uint8(memView.indexUint({index_: OFFSET_V, bytes_: 1}));\n    }\n\n    // ═════════════════════════════════════════════════ CALLDATA ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the calldata with the modified arguments:\n     * the existing arguments are prepended with the arguments from the prefix.\n     * @dev Given:\n     *  - `calldata = abi.encodeWithSelector(foo.selector, d, e);`\n     *  - `prefix = abi.encode(a, b, c);`\n     *  - `a`, `b`, `c` are arguments of static type (i.e. not dynamically sized ones)\n     *      Then:\n     *  - Function will return abi.encodeWithSelector(foo.selector, a, c, c, d, e)\n     *  - Returned calldata will trigger `foo(a, b, c, d, e)` when used for a contract call.\n     * Note: for clarification as to what types are considered static, see\n     * https://docs.soliditylang.org/en/latest/abi-spec.html#formal-specification-of-the-encoding\n     * @param callData  Calldata that needs to be modified\n     * @param prefix    ABI-encoded arguments to use as the first arguments in the new calldata\n     * @return Modified calldata having prefix as the first arguments.\n     */\n    function addPrefix(CallData callData, bytes memory prefix) internal view returns (bytes memory) {\n        // Prefix should occupy a whole amount of words in memory\n        if (!_fullWords(prefix.length)) revert UnformattedCallDataPrefix();\n        MemView[] memory views = new MemView[](3);\n        // Use payload's function selector\n        views[0] = abi.encodePacked(callData.callSelector()).ref();\n        // Use prefix as the first arguments\n        views[1] = prefix.ref();\n        // Use payload's remaining arguments\n        views[2] = callData.arguments();\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a CallData view over for the given payload.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(bytes memory payload) internal pure returns (CallData) {\n        return castToCallData(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a CallData view.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(MemView memView) internal pure returns (CallData) {\n        if (!isCallData(memView)) revert UnformattedCallData();\n        return CallData.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a valid calldata, i.e.\n     * a function selector, followed by arbitrary amount of arguments.\n     */\n    function isCallData(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Calldata should at least have a function selector\n        if (length \u003c SELECTOR_LENGTH) return false;\n        // The remainder of the calldata should be exactly N memory words (N \u003e= 0)\n        return _fullWords(length - SELECTOR_LENGTH);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(CallData callData) internal pure returns (MemView) {\n        return MemView.wrap(CallData.unwrap(callData));\n    }\n\n    /// @notice Returns callData's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(CallData callData) internal pure returns (bytes32) {\n        return callData.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ CALLDATA SLICING ══════════════════════════════════════════════════\n\n    /**\n     * @notice Returns amount of memory words (32 byte chunks) the function arguments\n     * occupy in the calldata.\n     * @dev This might differ from amount of arguments supplied, if any of the arguments\n     * occupies more than one memory slot. It is true, however, that argument part of the payload\n     * occupies exactly N words, even for dynamic types like `bytes`\n     */\n    function argumentWords(CallData callData) internal pure returns (uint256) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        // Equivalent of (length - SELECTOR_LENGTH) / 32\n        return (memView.len() - SELECTOR_LENGTH) \u003e\u003e 5;\n    }\n\n    /// @notice Returns selector for the provided calldata.\n    function callSelector(CallData callData) internal pure returns (bytes4) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return bytes4(memView.index({index_: OFFSET_SELECTOR, bytes_: SELECTOR_LENGTH}));\n    }\n\n    /// @notice Returns abi encoded arguments for the provided calldata.\n    function arguments(CallData callData) internal pure returns (MemView) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return memView.sliceFrom({index_: OFFSET_ARGUMENTS});\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if length is full amount of memory words (32 bytes).\n    function _fullWords(uint256 length) internal pure returns (bool) {\n        // The equivalent of length % 32 == 0\n        return length \u0026 31 == 0;\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n    function __Context_init() internal onlyInitializing {\n    }\n\n    function __Context_init_unchained() internal onlyInitializing {\n    }\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[50] private __gap;\n}\n\n// contracts/libs/merkle/MerkleTree.sol\n\n/// `BaseTree` is a struct representing incremental merkle tree.\n/// - Contains only the current branch.\n/// - The number of inserted leaves is stored externally, and is later supplied for tree operations.\n/// - Has a fixed height of `ORIGIN_TREE_HEIGHT`.\n/// - Can store up to `2 ** ORIGIN_TREE_HEIGHT - 1` leaves.\n/// \u003e Note: the hash function for the tree `H(x, y)` is defined as:\n/// \u003e - `H(0,0) = 0`\n/// \u003e - `H(x,y) = keccak256(x, y), when (x != 0 || y != 0)`\n/// ## Invariant for leafs\n/// - The leftmost empty leaf has `index == count`, where `count` is the amount of the inserted leafs so far.\n/// - Value for any empty leaf or node is bytes32(0).\n/// ## Invariant for current branch\n/// `branch[i]` is always the value of a node on the i-th level.\n/// Levels are numbered from leafs to root: `0 .. ORIGIN_TREE_HEIGHT`.\n/// `branch[i]` stores the value for the node, such that:\n//  - The node is a \"left child\" (e.g. has an even index).\n/// - The node must have two non-empty children.\n/// - Out of all level's \"left child\" nodes with \"non-empty children\",\n/// the one with the biggest index (the rightmost one) is stored as `branch[i]`.\n/// \u003e __`branch` could be used to form a proof of inclusion for the first empty leaf (`index == count`).__\n/// _Here is how:_\n/// - Let's walk along the path from the \"first empty leaf\" to the root.\n/// - i-th bit of the \"first empty leaf\" index (which is equal to `count`) determines if the path's node\n/// for this i-th level is a \"left child\" or a \"right child\".\n/// - i-th bit in `count` is 0 → we are the left child on this level → sibling is the right child\n/// that does not exist yet → `proof[i] = bytes32(0)`.\n/// - i-th bit in `count` is 1 → we are the right child on this level → sibling is the left child\n/// sibling is the rightmost \"left child\" node on the level → `proof[i] = branch[i]`.\n/// \u003e Therefore `proof[i] = (count \u0026 (1 \u003c\u003c i)) == 0 ? bytes32(0) : branch[i])`\nstruct BaseTree {\n    bytes32[ORIGIN_TREE_HEIGHT] branch;\n}\n\nusing MerkleTree for BaseTree global;\n\n/// `HistoricalTree` is an incremental merkle tree keeping track of its historical merkle roots.\n/// \u003e - `roots[N]` is the root of the tree after `N` leafs were inserted\n/// \u003e - `roots[0] == bytes32(0)`\n/// @param tree     Incremental merkle tree\n/// @param roots    Historical merkle roots of the tree\nstruct HistoricalTree {\n    BaseTree tree;\n    bytes32[] roots;\n}\n\nusing MerkleTree for HistoricalTree global;\n\n/// `DynamicTree` is a struct representing a Merkle Tree with `2**AGENT_TREE_HEIGHT` leaves.\n/// - A single operation is available: update value for leaf with an arbitrary index (which might be a non-empty leaf).\n/// - This is done by requesting the proof of inclusion for the old value, which is used to both\n/// verify the old value, and calculate the new root.\n/// \u003e Based on Original idea from [ER forum post](https://ethresear.ch/t/efficient-on-chain-dynamic-merkle-tree/11054).\nstruct DynamicTree {\n    bytes32 root;\n}\n\nusing MerkleTree for DynamicTree global;\n\n/// MerkleTree is work based on Nomad's Merkle.sol, which is used under MIT OR Apache-2.0\n/// [link](https://github.com/nomad-xyz/monorepo/blob/main/packages/contracts-core/contracts/libs/Merkle.sol).\n/// With the following changes:\n/// - Adapted for Solidity 0.8.x.\n/// - Amount of tree leaves stored externally.\n/// - Added thorough documentation.\n/// - `H(0,0) = 0` optimization from [ER forum post](https://ethresear.ch/t/optimizing-sparse-merkle-trees/3751/6).\n/// \u003e Nomad's Merkle.sol is work based on eth2 deposit contract, which is used under CC0-1.0\n///[link](https://github.com/ethereum/deposit_contract/blob/dev/deposit_contract/contracts/validator_registration.v.py).\n/// With the following changes:\n/// \u003e - Implemented in Solidity 0.7.6 (eth2 deposit contract implemented in Vyper).\n/// \u003e - `H() = keccak256()` is used as the hashing function instead of `sha256()`.\nlibrary MerkleTree {\n    /// @dev For root calculation we need at least one empty leaf, thus the minus one in the formula.\n    uint256 internal constant MAX_LEAVES = 2 ** ORIGIN_TREE_HEIGHT - 1;\n\n    // ═════════════════════════════════════════════════ BASE TREE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Inserts `node` into merkle tree\n     * @dev Reverts if tree is full\n     * @param newCount  Amount of inserted leaves in the tree after the insertion (i.e. current + 1)\n     * @param node      Element to insert into tree\n     */\n    function insertBase(BaseTree storage tree, uint256 newCount, bytes32 node) internal {\n        if (newCount \u003e MAX_LEAVES) revert MerkleTreeFull();\n        // We go up the tree following the branch from the empty leaf AFTER the just inserted one.\n        // We stop when we find the first \"right child\" node.\n        // Its sibling is now the rightmost \"left child\" node that has two non-empty children.\n        // Therefore we need to update `tree.branch` value on this level.\n        // One could see that `tree.branch` value on lower and higher levels remain unchanged.\n\n        // Loop invariant: `node` is the current level's value for the branch from JUST INSERTED leaf\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            if ((newCount \u0026 1) == 1) {\n                // Found the first \"right child\" node on the branch from EMPTY leaf\n                // `node` is the value for node on branch from JUST INSERTED leaf\n                // Which in this case is the \"left child\".\n                // We update tree.branch and exit\n                tree.branch[i] = node;\n                return;\n            }\n            // On the branch from EMPTY leaf this is still a \"left child\".\n            // Meaning on branch from JUST INSERTED leaf, `node` is a right child.\n            // We compute value for `node` parent using `tree.branch` invariant:\n            // This is the rightmost \"left child\" node, which would be sibling of `node`.\n            node = MerkleMath.getParent(tree.branch[i], node);\n            // Get the parent index, and go to the next tree level\n            newCount \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n        // As the loop should always end prematurely with the `return` statement,\n        // this code should be unreachable. We assert `false` just to be safe.\n        assert(false);\n    }\n\n    /**\n     * @notice Calculates and returns current root of the merkle tree.\n     * @param count     Current amount of inserted leaves in the tree\n     * @return current  Calculated root of `tree`\n     */\n    function rootBase(BaseTree storage tree, uint256 count) internal view returns (bytes32 current) {\n        // To calculate the root we follow the branch of first EMPTY leaf (index == count)\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            // Check if we are the left or the right child on the current level\n            if ((count \u0026 1) == 1) {\n                // We are the right child. Our sibling is the \"rightmost\" \"left-child\" node\n                // that has two non-empty children → sibling is `tree.branch[i]`\n                current = MerkleMath.getParent(tree.branch[i], current);\n            } else {\n                // We are the left child. Our sibling does not exist yet → sibling is EMPTY\n                current = MerkleMath.getParent(current, bytes32(0));\n            }\n            // Get the parent index, and go to the next tree level\n            count \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    // ══════════════════════════════════════════════ HISTORICAL TREE ══════════════════════════════════════════════════\n\n    /// @notice Initializes the historical roots for the tree by inserting an empty root.\n    // solhint-disable-next-line ordering\n    function initializeRoots(HistoricalTree storage tree) internal returns (bytes32 savedRoot) {\n        // This should only be called once, when the contract is initialized\n        assert(tree.roots.length == 0);\n        // Save root for empty merkle tree: bytes32(0)\n        tree.roots.push(savedRoot);\n    }\n\n    /// @notice Inserts a new leaf into the merkle tree.\n    /// @dev Reverts if tree is full.\n    /// @param node         Element to insert into tree\n    /// @return newRoot     Merkle root after the leaf was inserted\n    function insert(HistoricalTree storage tree, bytes32 node) internal returns (bytes32 newRoot) {\n        // Tree count after the new leaf will be inserted (we store roots[0] as root of empty tree)\n        uint256 newCount = tree.roots.length;\n        tree.tree.insertBase(newCount, node);\n        // Save the new root\n        newRoot = tree.tree.rootBase(newCount);\n        tree.roots.push(newRoot);\n    }\n\n    /// @notice Returns the historical root of the merkle tree.\n    /// @dev Reverts if not enough leafs have been inserted.\n    /// @param count            Amount of leafs in the tree at some point of time\n    /// @return historicalRoot  Merkle root after `count` leafs were inserted\n    function root(HistoricalTree storage tree, uint256 count) internal view returns (bytes32 historicalRoot) {\n        if (count \u003e= tree.roots.length) revert NotEnoughLeafs();\n        return tree.roots[count];\n    }\n\n    // ═══════════════════════════════════════════════ DYNAMIC TREE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Updates the value for the leaf with the given index in the Dynamic Merkle Tree.\n     * @dev Will revert if incorrect proof of inclusion for old value is supplied.\n     * @param tree          Dynamic merkle tree\n     * @param index         Index of the leaf to update\n     * @param oldValue      Previous value of the leaf\n     * @param branch        Proof of inclusion of previous value into the tree\n     * @param newValue      New leaf value to assign\n     * @return newRoot      New value for the Merkle Root after the leaf is updated\n     */\n    function update(\n        DynamicTree storage tree,\n        uint256 index,\n        bytes32 oldValue,\n        bytes32[] memory branch,\n        bytes32 newValue\n    ) internal returns (bytes32 newRoot) {\n        // Check that the old value + proof result in a correct root\n        if (MerkleMath.proofRoot(index, oldValue, branch, AGENT_TREE_HEIGHT) != tree.root) {\n            revert LeafNotProven();\n        }\n        // New root is new value + the same proof (values for sibling nodes are not updated)\n        newRoot = MerkleMath.proofRoot(index, newValue, branch, AGENT_TREE_HEIGHT);\n        // Write the new root\n        tree.root = newRoot;\n    }\n}\n\n// contracts/libs/stack/Tips.sol\n\n/// Tips is encoded data with \"tips paid for sending a base message\".\n/// Note: even though uint256 is also an underlying type for MemView, Tips is stored ON STACK.\ntype Tips is uint256;\n\nusing TipsLib for Tips global;\n\n/// # Tips\n/// Library for formatting _the tips part_ of _the base messages_.\n///\n/// ## How the tips are awarded\n/// Tips are paid for sending a base message, and are split across all the agents that\n/// made the message execution on destination chain possible.\n/// ### Summit tips\n/// Split between:\n///     - Guard posting a snapshot with state ST_G for the origin chain.\n///     - Notary posting a snapshot SN_N using ST_G. This creates attestation A.\n///     - Notary posting a message receipt after it is executed on destination chain.\n/// ### Attestation tips\n/// Paid to:\n///     - Notary posting attestation A to destination chain.\n/// ### Execution tips\n/// Paid to:\n///     - First executor performing a valid execution attempt (correct proofs, optimistic period over),\n///      using attestation A to prove message inclusion on origin chain, whether the recipient reverted or not.\n/// ### Delivery tips.\n/// Paid to:\n///     - Executor who successfully executed the message on destination chain.\n///\n/// ## Tips encoding\n/// - Tips occupy a single storage word, and thus are stored on stack instead of being stored in memory.\n/// - The actual tip values should be determined by multiplying stored values by divided by TIPS_MULTIPLIER=2**32.\n/// - Tips are packed into a single word of storage, while allowing real values up to ~8*10**28 for every tip category.\n/// \u003e The only downside is that the \"real tip values\" are now multiplies of ~4*10**9, which should be fine even for\n/// the chains with the most expensive gas currency.\n/// # Tips stack layout (from highest bits to lowest)\n///\n/// | Position   | Field          | Type   | Bytes | Description                                                |\n/// | ---------- | -------------- | ------ | ----- | ---------------------------------------------------------- |\n/// | (032..024] | summitTip      | uint64 | 8     | Tip for agents interacting with Summit contract            |\n/// | (024..016] | attestationTip | uint64 | 8     | Tip for Notary posting attestation to Destination contract |\n/// | (016..008] | executionTip   | uint64 | 8     | Tip for valid execution attempt on destination chain       |\n/// | (008..000] | deliveryTip    | uint64 | 8     | Tip for successful message delivery on destination chain   |\n\nlibrary TipsLib {\n    using SafeCast for uint256;\n\n    /// @dev Amount of bits to shift to summitTip field\n    uint256 private constant SHIFT_SUMMIT_TIP = 24 * 8;\n    /// @dev Amount of bits to shift to attestationTip field\n    uint256 private constant SHIFT_ATTESTATION_TIP = 16 * 8;\n    /// @dev Amount of bits to shift to executionTip field\n    uint256 private constant SHIFT_EXECUTION_TIP = 8 * 8;\n\n    // ═══════════════════════════════════════════════════ TIPS ════════════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips with the given fields\n    /// @param summitTip_        Tip for agents interacting with Summit contract, divided by TIPS_MULTIPLIER\n    /// @param attestationTip_   Tip for Notary posting attestation to Destination contract, divided by TIPS_MULTIPLIER\n    /// @param executionTip_     Tip for valid execution attempt on destination chain, divided by TIPS_MULTIPLIER\n    /// @param deliveryTip_      Tip for successful message delivery on destination chain, divided by TIPS_MULTIPLIER\n    function encodeTips(uint64 summitTip_, uint64 attestationTip_, uint64 executionTip_, uint64 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // forgefmt: disable-next-item\n        return Tips.wrap(\n            uint256(summitTip_) \u003c\u003c SHIFT_SUMMIT_TIP |\n            uint256(attestationTip_) \u003c\u003c SHIFT_ATTESTATION_TIP |\n            uint256(executionTip_) \u003c\u003c SHIFT_EXECUTION_TIP |\n            uint256(deliveryTip_)\n        );\n    }\n\n    /// @notice Convenience function to encode tips with uint256 values.\n    function encodeTips256(uint256 summitTip_, uint256 attestationTip_, uint256 executionTip_, uint256 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // In practice, the tips amounts are not supposed to be higher than 2**96, and with 32 bits of granularity\n        // using uint64 is enough to store the values. However, we still check for overflow just in case.\n        // TODO: consider using Number type to store the tips values.\n        return encodeTips({\n            summitTip_: (summitTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            attestationTip_: (attestationTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            executionTip_: (executionTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            deliveryTip_: (deliveryTip_ \u003e\u003e TIPS_GRANULARITY).toUint64()\n        });\n    }\n\n    /// @notice Wraps the padded encoded tips into a Tips-typed value.\n    /// @dev There is no actual padding here, as the underlying type is already uint256,\n    /// but we include this function for consistency and to be future-proof, if tips will eventually use anything\n    /// smaller than uint256.\n    function wrapPadded(uint256 paddedTips) internal pure returns (Tips) {\n        return Tips.wrap(paddedTips);\n    }\n\n    /**\n     * @notice Returns a formatted Tips payload specifying empty tips.\n     * @return Formatted tips\n     */\n    function emptyTips() internal pure returns (Tips) {\n        return Tips.wrap(0);\n    }\n\n    /// @notice Returns tips's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Tips tips) internal pure returns (bytes32 hashedTips) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store tips in scratch space\n            mstore(0, tips)\n            // Compute hash of tips padded to 32 bytes\n            hashedTips := keccak256(0, 32)\n        }\n    }\n\n    // ═══════════════════════════════════════════════ TIPS SLICING ════════════════════════════════════════════════════\n\n    /// @notice Returns summitTip field\n    function summitTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_SUMMIT_TIP);\n    }\n\n    /// @notice Returns attestationTip field\n    function attestationTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_ATTESTATION_TIP);\n    }\n\n    /// @notice Returns executionTip field\n    function executionTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_EXECUTION_TIP);\n    }\n\n    /// @notice Returns deliveryTip field\n    function deliveryTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips));\n    }\n\n    // ════════════════════════════════════════════════ TIPS VALUE ═════════════════════════════════════════════════════\n\n    /// @notice Returns total value of the tips payload.\n    /// This is the sum of the encoded values, scaled up by TIPS_MULTIPLIER\n    function value(Tips tips) internal pure returns (uint256 value_) {\n        value_ = uint256(tips.summitTip()) + tips.attestationTip() + tips.executionTip() + tips.deliveryTip();\n        value_ \u003c\u003c= TIPS_GRANULARITY;\n    }\n\n    /// @notice Increases the delivery tip to match the new value.\n    function matchValue(Tips tips, uint256 newValue) internal pure returns (Tips newTips) {\n        uint256 oldValue = tips.value();\n        if (newValue \u003c oldValue) revert TipsValueTooLow();\n        // We want to increase the delivery tip, while keeping the other tips the same\n        unchecked {\n            uint256 delta = (newValue - oldValue) \u003e\u003e TIPS_GRANULARITY;\n            // `delta` fits into uint224, as TIPS_GRANULARITY is 32, so this never overflows uint256.\n            // In practice, this will never overflow uint64 as well, but we still check it just in case.\n            if (delta + tips.deliveryTip() \u003e type(uint64).max) revert TipsOverflow();\n            // Delivery tips occupy lowest 8 bytes, so we can just add delta to the tips value\n            // to effectively increase the delivery tip (knowing that delta fits into uint64).\n            newTips = Tips.wrap(Tips.unwrap(tips) + delta);\n        }\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    function __Ownable_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable_init_unchained() internal onlyInitializing {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n    function __Ownable2Step_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable2Step_init_unchained() internal onlyInitializing {\n    }\n    address private _pendingOwner;\n\n    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Returns the address of the pending owner.\n     */\n    function pendingOwner() public view virtual returns (address) {\n        return _pendingOwner;\n    }\n\n    /**\n     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual override onlyOwner {\n        _pendingOwner = newOwner;\n        emit OwnershipTransferStarted(owner(), newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual override {\n        delete _pendingOwner;\n        super._transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev The new owner accepts the ownership transfer.\n     */\n    function acceptOwnership() public virtual {\n        address sender = _msgSender();\n        require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n        _transferOwnership(sender);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// contracts/libs/memory/State.sol\n\n/// State is a memory view over a formatted state payload.\ntype State is uint256;\n\nusing StateLib for State global;\n\n/// # State\n/// State structure represents the state of Origin contract at some point of time.\n/// - State is structured in a way to track the updates of the Origin Merkle Tree.\n/// - State includes root of the Origin Merkle Tree, origin domain and some additional metadata.\n/// ## Origin Merkle Tree\n/// Hash of every sent message is inserted in the Origin Merkle Tree, which changes\n/// the value of Origin Merkle Root (which is the root for the mentioned tree).\n/// - Origin has a single Merkle Tree for all messages, regardless of their destination domain.\n/// - This leads to Origin state being updated if and only if a message was sent in a block.\n/// - Origin contract is a \"source of truth\" for states: a state is considered \"valid\" in its Origin,\n/// if it matches the state of the Origin contract after the N-th (nonce) message was sent.\n///\n/// # Memory layout of State fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                    |\n/// | ---------- | ----------- | ------- | ----- | ------------------------------ |\n/// | [000..032) | root        | bytes32 | 32    | Root of the Origin Merkle Tree |\n/// | [032..036) | origin      | uint32  | 4     | Domain where Origin is located |\n/// | [036..040) | nonce       | uint32  | 4     | Amount of sent messages        |\n/// | [040..045) | blockNumber | uint40  | 5     | Block of last sent message     |\n/// | [045..050) | timestamp   | uint40  | 5     | Time of last sent message      |\n/// | [050..062) | gasData     | uint96  | 12    | Gas data for the chain         |\n///\n/// @dev State could be used to form a Snapshot to be signed by a Guard or a Notary.\nlibrary StateLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_ROOT = 0;\n    uint256 private constant OFFSET_ORIGIN = 32;\n    uint256 private constant OFFSET_NONCE = 36;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 40;\n    uint256 private constant OFFSET_TIMESTAMP = 45;\n    uint256 private constant OFFSET_GAS_DATA = 50;\n\n    // ═══════════════════════════════════════════════════ STATE ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted State payload with provided fields\n     * @param root_         New merkle root\n     * @param origin_       Domain of Origin's chain\n     * @param nonce_        Nonce of the merkle root\n     * @param blockNumber_  Block number when root was saved in Origin\n     * @param timestamp_    Block timestamp when root was saved in Origin\n     * @param gasData_      Gas data for the chain\n     * @return Formatted state\n     */\n    function formatState(\n        bytes32 root_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_,\n        GasData gasData_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(root_, origin_, nonce_, blockNumber_, timestamp_, gasData_);\n    }\n\n    /**\n     * @notice Returns a State view over the given payload.\n     * @dev Will revert if the payload is not a state.\n     */\n    function castToState(bytes memory payload) internal pure returns (State) {\n        return castToState(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a State view.\n     * @dev Will revert if the memory view is not over a state.\n     */\n    function castToState(MemView memView) internal pure returns (State) {\n        if (!isState(memView)) revert UnformattedState();\n        return State.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted State.\n    function isState(MemView memView) internal pure returns (bool) {\n        return memView.len() == STATE_LENGTH;\n    }\n\n    /// @notice Returns the hash of a State, that could be later signed by a Guard to signal\n    /// that the state is invalid.\n    function hashInvalid(State state) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(stateInvalidSalt, keccak(state))\n        return state.unwrap().keccakSalted(STATE_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(State state) internal pure returns (MemView) {\n        return MemView.wrap(State.unwrap(state));\n    }\n\n    /// @notice Compares two State structures.\n    function equals(State a, State b) internal pure returns (bool) {\n        // Length of a State payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═══════════════════════════════════════════════ STATE HASHING ═══════════════════════════════════════════════════\n\n    /// @notice Returns the hash of the State.\n    /// @dev We are using the Merkle Root of a tree with two leafs (see below) as state hash.\n    function leaf(State state) internal pure returns (bytes32) {\n        (bytes32 leftLeaf_, bytes32 rightLeaf_) = state.subLeafs();\n        // Final hash is the parent of these leafs\n        return keccak256(bytes.concat(leftLeaf_, rightLeaf_));\n    }\n\n    /// @notice Returns \"sub-leafs\" of the State. Hash of these \"sub leafs\" is going to be used\n    /// as a \"state leaf\" in the \"Snapshot Merkle Tree\".\n    /// This enables proving that leftLeaf = (root, origin) was a part of the \"Snapshot Merkle Tree\",\n    /// by combining `rightLeaf` with the remainder of the \"Snapshot Merkle Proof\".\n    function subLeafs(State state) internal pure returns (bytes32 leftLeaf_, bytes32 rightLeaf_) {\n        MemView memView = state.unwrap();\n        // Left leaf is (root, origin)\n        leftLeaf_ = memView.prefix({len_: OFFSET_NONCE}).keccak();\n        // Right leaf is (metadata), or (nonce, blockNumber, timestamp)\n        rightLeaf_ = memView.sliceFrom({index_: OFFSET_NONCE}).keccak();\n    }\n\n    /// @notice Returns the left \"sub-leaf\" of the State.\n    function leftLeaf(bytes32 root_, uint32 origin_) internal pure returns (bytes32) {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(root_, origin_));\n    }\n\n    /// @notice Returns the right \"sub-leaf\" of the State.\n    function rightLeaf(uint32 nonce_, uint40 blockNumber_, uint40 timestamp_, GasData gasData_)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(nonce_, blockNumber_, timestamp_, gasData_));\n    }\n\n    // ═══════════════════════════════════════════════ STATE SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns a historical Merkle root from the Origin contract.\n    function root(State state) internal pure returns (bytes32) {\n        return state.unwrap().index({index_: OFFSET_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns domain of chain where the Origin contract is deployed.\n    function origin(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns nonce of Origin contract at the time, when `root` was the Merkle root.\n    function nonce(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when `root` was saved in Origin.\n    function blockNumber(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when `root` was saved in Origin.\n    /// @dev This is the timestamp according to the origin chain.\n    function timestamp(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n\n    /// @notice Returns gas data for the chain.\n    function gasData(State state) internal pure returns (GasData) {\n        return GasDataLib.wrapGasData(state.unwrap().indexUint({index_: OFFSET_GAS_DATA, bytes_: GAS_DATA_LENGTH}));\n    }\n}\n\n// contracts/libs/memory/BaseMessage.sol\n\n/// BaseMessage is a memory view over the base message supported by Origin-Destination\ntype BaseMessage is uint256;\n\nusing BaseMessageLib for BaseMessage global;\n\n/// BaseMessage structure represents a base message sent via the Origin-Destination contracts.\n/// - It only contains data relevant to the base message, the rest of data is encoded in the message header.\n/// - `sender` and `recipient` for EVM chains are EVM addresses casted to bytes32, while preserving left-alignment.\n/// - `tips` and `request` parameters are specified by a message sender\n/// \u003e Origin will calculate minimum tips for given request and content length, and will reject messages with tips\n/// lower than that.\n///\n/// # Memory layout of BaseMessage fields\n///\n/// | Position   | Field     | Type    | Bytes | Description                            |\n/// | ---------- | --------- | ------- | ----- | -------------------------------------- |\n/// | [000..032) | tips      | uint256 | 32    | Encoded tips paid on origin chain      |\n/// | [032..064) | sender    | bytes32 | 32    | Sender address on origin chain         |\n/// | [064..096) | recipient | bytes32 | 32    | Recipient address on destination chain |\n/// | [096..116) | request   | uint160 | 20    | Encoded request for message execution  |\n/// | [104..AAA) | content   | bytes   | ??    | Content to be passed to recipient      |\nlibrary BaseMessageLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_TIPS = 0;\n    uint256 private constant OFFSET_SENDER = 32;\n    uint256 private constant OFFSET_RECIPIENT = 64;\n    uint256 private constant OFFSET_REQUEST = OFFSET_RECIPIENT + TIPS_LENGTH;\n    uint256 private constant OFFSET_CONTENT = OFFSET_REQUEST + REQUEST_LENGTH;\n\n    // ═══════════════════════════════════════════════ BASE MESSAGE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted BaseMessage payload with provided fields.\n     * @param tips_         Encoded tips information\n     * @param sender_       Sender address on origin chain\n     * @param recipient_    Recipient address on destination chain\n     * @param request_      Encoded request for message execution\n     * @param content_      Raw content to be passed to recipient on destination chain\n     * @return Formatted base message\n     */\n    function formatBaseMessage(Tips tips_, bytes32 sender_, bytes32 recipient_, Request request_, bytes memory content_)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return abi.encodePacked(tips_, sender_, recipient_, request_, content_);\n    }\n\n    /**\n     * @notice Returns a BaseMessage view over the given payload.\n     * @dev Will revert if the payload is not a base message.\n     */\n    function castToBaseMessage(bytes memory payload) internal pure returns (BaseMessage) {\n        return castToBaseMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a BaseMessage view.\n     * @dev Will revert if the memory view is not over a base message payload.\n     */\n    function castToBaseMessage(MemView memView) internal pure returns (BaseMessage) {\n        if (!isBaseMessage(memView)) revert UnformattedBaseMessage();\n        return BaseMessage.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted BaseMessage.\n    function isBaseMessage(MemView memView) internal pure returns (bool) {\n        // Check if sender, recipient, tips fields exist\n        return (memView.len() \u003e= OFFSET_CONTENT);\n        // Content could be empty, so we don't check that\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(BaseMessage baseMessage) internal pure returns (MemView) {\n        return MemView.wrap(BaseMessage.unwrap(baseMessage));\n    }\n\n    /// @notice Returns baseMessage's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        // We hash \"tips\" and \"everything but tips\" to make tips proofs easier to verify\n        return MerkleMath.getParent(baseMessage.tips().leaf(), baseMessage.bodyLeaf());\n    }\n\n    /// @notice Returns hash for the \"everything but tips\" part of the base message.\n    function bodyLeaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_SENDER}).keccak();\n    }\n\n    // ═══════════════════════════════════════════ BASE MESSAGE SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips paid on origin chain.\n    function tips(BaseMessage baseMessage) internal pure returns (Tips) {\n        return TipsLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_TIPS, bytes_: TIPS_LENGTH})));\n    }\n\n    /// @notice Returns sender address on origin chain.\n    function sender(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_SENDER, bytes_: 32});\n    }\n\n    /// @notice Returns recipient address on destination chain.\n    function recipient(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_RECIPIENT, bytes_: 32});\n    }\n\n    /// @notice Returns an encoded request for message execution on destination chain.\n    function request(BaseMessage baseMessage) internal pure returns (Request) {\n        return RequestLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_REQUEST, bytes_: REQUEST_LENGTH})));\n    }\n\n    /// @notice Returns an untyped memory view over the content to be passed to recipient.\n    function content(BaseMessage baseMessage) internal pure returns (MemView) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_CONTENT});\n    }\n}\n\n// contracts/base/MessagingBase.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for all messaging contracts.\n * - Provides context on the local chain's domain.\n * - Provides ownership functionality.\n * - Will be providing pausing functionality when it is implemented.\n */\nabstract contract MessagingBase is MultiCallable, Versioned, Ownable2StepUpgradeable {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @notice Domain of the local chain, set once upon contract creation\n    uint32 public immutable localDomain;\n    // @notice Domain of the Synapse chain, set once upon contract creation\n    uint32 public immutable synapseDomain;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev gap for upgrade safety\n    uint256[50] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    constructor(string memory version_, uint32 synapseDomain_) Versioned(version_) {\n        localDomain = ChainContext.chainId();\n        synapseDomain = synapseDomain_;\n    }\n\n    // TODO: Implement pausing\n\n    /**\n     * @dev Should be impossible to renounce ownership;\n     * we override OpenZeppelin OwnableUpgradeable's\n     * implementation of renounceOwnership to make it a no-op\n     */\n    function renounceOwnership() public override onlyOwner {} //solhint-disable-line no-empty-blocks\n}\n\n// contracts/libs/memory/Message.sol\n\n/// Message is a memory over over a formatted message payload.\ntype Message is uint256;\n\nusing MessageLib for Message global;\n\n/// Library for formatting the various messages supported by Origin and Destination.\n///\n/// # Message memory layout\n///\n/// | Position   | Field  | Type    | Bytes | Description                                             |\n/// | ---------- | ------ | ------- | ----- | ------------------------------------------------------- |\n/// | [000..017) | header | uint136 | 17    | Encoded general routing information for the message     |\n/// | [017..AAA) | body   | bytes   | ??    | Formatted payload (according to flag) with message body |\nlibrary MessageLib {\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MemViewLib for bytes;\n    using HeaderLib for MemView;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_HEADER = 0;\n    uint256 private constant OFFSET_BODY = OFFSET_HEADER + HEADER_LENGTH;\n\n    // ══════════════════════════════════════════════════ MESSAGE ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns formatted message with provided fields.\n     * @param header_   Encoded general routing information for the message\n     * @param body_     Formatted payload (according to flag) with message body\n     * @return Formatted message\n     */\n    function formatMessage(Header header_, bytes memory body_) internal pure returns (bytes memory) {\n        return abi.encodePacked(header_, body_);\n    }\n\n    /**\n     * @notice Returns a Message view over for the given payload.\n     * @dev Will revert if the payload is not a message payload.\n     */\n    function castToMessage(bytes memory payload) internal pure returns (Message) {\n        return castToMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Message view.\n     * @dev Will revert if the memory view is not over a message payload.\n     */\n    function castToMessage(MemView memView) internal pure returns (Message) {\n        if (!isMessage(memView)) revert UnformattedMessage();\n        return Message.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Message.\n     */\n    function isMessage(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Check if headers exist in the payload\n        if (length \u003c OFFSET_BODY) return false;\n        // Check that Header is valid\n        uint256 paddedHeader = _header(memView);\n        if (!HeaderLib.isHeader(paddedHeader)) return false;\n        // Check that body is formatted according to the flag\n        // Only Base/Manager message flags exist\n        if (HeaderLib.wrapPadded(paddedHeader).flag() == MessageFlag.Base) {\n            // Check if body is a formatted base message\n            return _body(memView).isBaseMessage();\n        } else {\n            // Check if body is a formatted calldata for AgentManager call\n            return _body(memView).isCallData();\n        }\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Message message) internal pure returns (MemView) {\n        return MemView.wrap(Message.unwrap(message));\n    }\n\n    /// @notice Returns message's hash: a leaf to be inserted in the Merkle tree.\n    function leaf(Message message) internal pure returns (bytes32) {\n        // We hash header and body separately to make message proofs easier to verify\n        Header header_ = message.header();\n        // Only Base/Manager message flags exist\n        if (header_.flag() == MessageFlag.Base) {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToBaseMessage().leaf());\n        } else {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToCallData().leaf());\n        }\n    }\n\n    // ══════════════════════════════════════════════ MESSAGE SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns message's encoded header field.\n    function header(Message message) internal pure returns (Header) {\n        return HeaderLib.wrapPadded((message.unwrap().indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH})));\n    }\n\n    /// @notice Returns message's body field as an untyped memory view.\n    function body(Message message) internal pure returns (MemView) {\n        MemView memView = message.unwrap();\n        return _body(memView);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns message's padded header without checking that it is a valid header.\n    function _header(MemView memView) private pure returns (uint256) {\n        return memView.indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH});\n    }\n\n    /// @dev Returns an untyped memory view over the body field without checking\n    /// if the whole payload or the body are properly formatted.\n    function _body(MemView memView) private pure returns (MemView) {\n        return memView.sliceFrom({index_: OFFSET_BODY});\n    }\n}\n\n// contracts/base/AgentSecured.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for messaging contracts that are secured by the agent manager.\n * `AgentSecured` relies on `AgentManager` to provide the following functionality:\n * - Keep track of agents and their statuses.\n * - Pass agent-signed statements that were verified by the agent manager.\n * - These statements are considered valid indefinitely, unless the agent is disputed.\n * - Disputes are opened and resolved by the agent manager.\n * \u003e `AgentSecured` implementation should never use statements signed by agents that are disputed.\n */\nabstract contract AgentSecured is MessagingBase, IAgentSecured {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    address public immutable agentManager;\n\n    /// @inheritdoc IAgentSecured\n    address public immutable inbox;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    // (agent index =\u003e their dispute status: flag, openedAt, resolvedAt)\n    mapping(uint32 =\u003e DisputeStatus) internal _disputes;\n\n    /// @dev gap for upgrade safety\n    uint256[49] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    modifier onlyAgentManager() {\n        if (msg.sender != agentManager) revert CallerNotAgentManager();\n        _;\n    }\n\n    modifier onlyInbox() {\n        if (msg.sender != inbox) revert CallerNotInbox();\n        _;\n    }\n\n    constructor(string memory version_, uint32 synapseDomain_, address agentManager_, address inbox_)\n        MessagingBase(version_, synapseDomain_)\n    {\n        agentManager = agentManager_;\n        inbox = inbox_;\n    }\n\n    // ════════════════════════════════════════════ ONLY AGENT MANAGER ═════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external onlyAgentManager {\n        uint40 openedAt = ChainContext.blockTimestamp();\n        DisputeStatus memory status = DisputeStatus({flag: DisputeFlag.Pending, openedAt: openedAt, resolvedAt: 0});\n        _disputes[guardIndex] = status;\n        _disputes[notaryIndex] = status;\n    }\n\n    /// @inheritdoc IAgentSecured\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external onlyAgentManager {\n        // Update the dispute status of the slashed agent first.\n        uint40 resolvedAt = ChainContext.blockTimestamp();\n        _disputes[slashedIndex].flag = DisputeFlag.Slashed;\n        _disputes[slashedIndex].resolvedAt = resolvedAt;\n        // Mark the rival agent as not disputed, if there was an ongoing dispute.\n        if (rivalIndex != 0) {\n            _disputes[rivalIndex].flag = DisputeFlag.None;\n            _disputes[rivalIndex].resolvedAt = resolvedAt;\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function agentStatus(address agent) external view returns (AgentStatus memory) {\n        return _agentStatus(agent);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status) {\n        return _getAgent(index);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory) {\n        return _disputes[agentIndex];\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns status of the given agent: (flag, domain, index).\n    function _agentStatus(address agent) internal view returns (AgentStatus memory) {\n        return IAgentManager(agentManager).agentStatus(agent);\n    }\n\n    /// @dev Returns agent and their status for a given agent index. Returns zero values for non existing indexes.\n    function _getAgent(uint256 index) internal view returns (address agent, AgentStatus memory status) {\n        return IAgentManager(agentManager).getAgent(index);\n    }\n\n    /// @dev Checks if a Dispute exists for the given Notary. This function returns true, if\n    /// Notary is in ongoing Dispute, or if Dispute was resolved not in Notary's favor.\n    /// In both cases we can't trust Notary's data.\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeExists(uint32 notaryIndex) internal view returns (bool) {\n        return _disputes[notaryIndex].flag != DisputeFlag.None;\n    }\n\n    /// @dev Checks if a Notary recently won a Dispute and is still in the \"post-dispute\" timeout period.\n    /// In this period we still can't trust Notary's data, though we can optimistically assume that\n    /// that the data will be correct after the timeout (assuming no new Disputes are opened).\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeTimeout(uint32 notaryIndex) internal view returns (bool) {\n        DisputeStatus memory status = _disputes[notaryIndex];\n        // Exit early if Notary is in ongoing Dispute / slashed.\n        if (status.flag != DisputeFlag.None) return false;\n        // Check if Notary has been in any Dispute at all.\n        if (status.openedAt == 0) return false;\n        // Otherwise check if the Dispute timeout is still active.\n        return block.timestamp \u003c status.resolvedAt + DISPUTE_TIMEOUT_NOTARY;\n    }\n}\n\n// contracts/hubs/StateHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StateHub` is a parent contract for `Origin`. It is responsible for the following:\n/// - Keeping track of the historical Origin Merkle Tree containing all the message hashes.\n/// - Keeping track of the historical Origin States, as well as verifying their validity.\nabstract contract StateHub is AgentSecured, StateHubEvents, IStateHub {\n    using SafeCast for uint256;\n    using StateLib for bytes;\n\n    struct OriginState {\n        uint40 blockNumber;\n        uint40 timestamp;\n        GasData gasData;\n    }\n    // Bits left for tight packing: 80\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Historical Merkle Tree\n    /// Note: Takes two storage slots\n    HistoricalTree private _tree;\n\n    /// @dev All historical contract States\n    OriginState[] private _originStates;\n\n    /// @dev gap for upgrade safety\n    uint256[47] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IStateHub\n    function isValidState(bytes memory statePayload) external view returns (bool isValid) {\n        // This will revert if payload is not a formatted state\n        State state = statePayload.castToState();\n        return _isValidState(state);\n    }\n\n    /// @inheritdoc IStateHub\n    function statesAmount() external view returns (uint256) {\n        return _originStates.length;\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestLatestState() external view returns (bytes memory stateData) {\n        // This never underflows, assuming the contract was initialized\n        return suggestState(_nextNonce() - 1);\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestState(uint32 nonce) public view returns (bytes memory stateData) {\n        // This will revert if nonce is out of range\n        bytes32 root = _tree.root(nonce);\n        return _formatOriginState(_originStates[nonce], root, localDomain, nonce);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Initializes the saved states list by inserting a state for an empty Merkle Tree.\n    function _initializeStates() internal {\n        // This should only be called once, when the contract is initialized\n        // This will revert if _tree.roots is non-empty\n        bytes32 savedRoot = _tree.initializeRoots();\n        // Save root for empty merkle _tree with block number and timestamp of initialization\n        _saveState(savedRoot, _toOriginState());\n    }\n\n    /// @dev Inserts leaf into the Merkle Tree and saves the updated origin State.\n    function _insertAndSave(bytes32 leaf) internal {\n        bytes32 newRoot = _tree.insert(leaf);\n        _saveState(newRoot, _toOriginState());\n    }\n\n    /// @dev Saves an updated state of the Origin contract\n    function _saveState(bytes32 root, OriginState memory state) internal {\n        uint32 nonce = _nextNonce();\n        _originStates.push(state);\n        // Emit event with raw state data\n        emit StateSaved(_formatOriginState(state, root, localDomain, nonce));\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns nonce of the next sent message: the amount of saved States so far.\n    /// This always equals to \"total amount of sent messages\" plus 1.\n    function _nextNonce() internal view returns (uint32) {\n        // TODO: consider using more than 32 bits for origin nonces\n        return _originStates.length.toUint32();\n    }\n\n    /// @dev Checks if a state is valid, i.e. if it matches the historical one.\n    /// Reverts, if state refers to another Origin contract.\n    function _isValidState(State state) internal view returns (bool) {\n        // Check if state refers to this contract\n        if (state.origin() != localDomain) revert IncorrectOriginDomain();\n        // Check if nonce exists\n        uint32 nonce = state.nonce();\n        if (nonce \u003e= _originStates.length) return false;\n        // Check if state root matches the historical one\n        if (state.root() != _tree.root(nonce)) return false;\n        // Check if state metadata matches the historical one\n        return _areEqual(state, _originStates[nonce]);\n    }\n\n    // ═════════════════════════════════════════════ STRUCT FORMATTING ═════════════════════════════════════════════════\n\n    /// @dev Returns a formatted payload for a stored OriginState.\n    function _formatOriginState(OriginState memory originState, bytes32 root, uint32 origin, uint32 nonce)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return StateLib.formatState({\n            root_: root,\n            origin_: origin,\n            nonce_: nonce,\n            blockNumber_: originState.blockNumber,\n            timestamp_: originState.timestamp,\n            gasData_: originState.gasData\n        });\n    }\n\n    /// @dev Child contract should implement the logic for getting the current gas data from the gas oracle\n    /// to be saved as part of the Origin State.\n    // solhint-disable-next-line ordering\n    function _fetchGasData() internal view virtual returns (GasData);\n\n    /// @dev Returns a OriginState struct to save in the contract.\n    function _toOriginState() internal view returns (OriginState memory originState) {\n        originState.blockNumber = ChainContext.blockNumber();\n        originState.timestamp = ChainContext.blockTimestamp();\n        originState.gasData = _fetchGasData();\n    }\n\n    /// @dev Checks that a state and its Origin representation are equal.\n    function _areEqual(State state, OriginState memory originState) internal pure returns (bool) {\n        return state.blockNumber() == originState.blockNumber \u0026\u0026 state.timestamp() == originState.timestamp;\n    }\n}\n\n// contracts/Origin.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Origin` contract is used for sending messages to remote chains. It is done\n/// by inserting the message hashes into the Origin Merkle, which makes it possible to\n/// prove that message was sent using the Merkle proof against the Origin Merkle Root. This essentially\n/// compresses the list of messages into a single 32-byte value that needs to be stored on the destination chain.\n/// `Origin` is responsible for the following:\n/// - Formatting the sent message payloads, and inserting their hashes into the Origin Merkle Tree.\n/// - Keeping track of its own historical states (see parent contract `StateHub`).\n/// - Enforcing minimum tip values for sent base messages based on the provided execution requests.\n/// - Distributing the collected tips upon request from a local `AgentManager` contract.\ncontract Origin is StateHub, OriginEvents, InterfaceOrigin {\n    using MemViewLib for bytes;\n    using MessageLib for bytes;\n    using TipsLib for bytes;\n    using TypeCasts for address;\n\n    address public immutable gasOracle;\n\n    modifier onlyRemoteDestination(uint32 destination) {\n        if (destination == localDomain) revert IncorrectDestinationDomain();\n        _;\n    }\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_, address gasOracle_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {\n        gasOracle = gasOracle_;\n    }\n\n    /// @notice Initializes Origin contract:\n    /// - msg.sender is set as contract owner\n    /// - State of \"empty merkle tree\" is saved\n    function initialize() external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize \"states\": state of an \"empty merkle tree\" is saved\n        _initializeStates();\n    }\n\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable onlyRemoteDestination(destination) returns (uint32 messageNonce, bytes32 messageHash) {\n        // Check that content is not too large\n        if (content.length \u003e MAX_CONTENT_BYTES) revert ContentLengthTooBig();\n        // This will revert if msg.value is lower than value of minimum tips\n        Tips tips = _getMinimumTips(destination, paddedRequest, content.length).matchValue(msg.value);\n        Request request = RequestLib.wrapPadded(paddedRequest);\n        // Format the BaseMessage body\n        bytes memory body = BaseMessageLib.formatBaseMessage({\n            sender_: msg.sender.addressToBytes32(),\n            recipient_: recipient,\n            tips_: tips,\n            request_: request,\n            content_: content\n        });\n        // Send the message\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Base, body);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        onlyAgentManager\n        onlyRemoteDestination(destination)\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // AgentManager (checked via modifier) is responsible for constructing the calldata payload correctly.\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Manager, payload);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function withdrawTips(address recipient, uint256 amount) external onlyAgentManager {\n        if (address(this).balance \u003c amount) revert InsufficientEthBalance();\n        (bool success,) = recipient.call{value: amount}(\"\");\n        if (!success) revert EthTransferFailed();\n        emit TipWithdrawalCompleted(recipient, amount);\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue)\n    {\n        return _getMinimumTips(destination, paddedRequest, contentLength).value();\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Sends the given message to the specified destination. Message hash is inserted\n    /// into the Origin Merkle Tree, which will enable message execution on destination chain.\n    function _sendMessage(uint32 destination, uint32 optimisticPeriod, MessageFlag flag, bytes memory body)\n        internal\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // Format the message header\n        messageNonce = _nextNonce();\n        Header header = flag.encodeHeader({\n            origin_: localDomain,\n            nonce_: messageNonce,\n            destination_: destination,\n            optimisticPeriod_: optimisticPeriod\n        });\n        // Format the full message payload\n        bytes memory msgPayload = MessageLib.formatMessage(header, body);\n        // Insert new leaf into the Origin Merkle Tree and save the updated state\n        messageHash = msgPayload.castToMessage().leaf();\n        _insertAndSave(messageHash);\n        // Emit event with message information\n        emit Sent(messageHash, messageNonce, destination, msgPayload);\n        // Update the gas oracle data. We do this after the provided tips are checked so that\n        // the provided message is sent in the event that the gas oracle data is updated to a higher value.\n        InterfaceGasOracle(gasOracle).updateGasData(destination);\n        // TODO: consider doing this before the message is sent, while adjusting GasOracle.getMinimumTips() to\n        // use the pending gas oracle data.\n    }\n\n    /// @dev Returns the minimum tips for sending a message to the given destination with the given request and content.\n    function _getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        internal\n        view\n        returns (Tips)\n    {\n        return\n            TipsLib.wrapPadded(InterfaceGasOracle(gasOracle).getMinimumTips(destination, paddedRequest, contentLength));\n    }\n\n    /// @dev Gets the current gas data from the gas oracle to be saved as part of the Origin State.\n    function _fetchGasData() internal view override returns (GasData) {\n        return GasDataLib.wrapGasData(InterfaceGasOracle(gasOracle).getGasData());\n    }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"","srcMapRuntime":"","abiDefinition":[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"custom:oz-upgrades-unsafe-allow":"constructor constructor() {     _disableInitializers(); } ``` ====","details":"This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. The initialization functions use a version number. Once a version number is used, it is consumed and cannot be reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in case an upgrade adds a module that needs to be initialized. For example: [.hljs-theme-light.nopadding] ```solidity contract MyToken is ERC20Upgradeable {     function initialize() initializer public {         __ERC20_init(\"MyToken\", \"MTK\");     } } contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {     function initializeV2() reinitializer(2) public {         __ERC20Permit_init(\"MyToken\");     } } ``` TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. [CAUTION] ==== Avoid leaving a contract uninitialized. An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: [.hljs-theme-light.nopadding] ```","events":{"Initialized(uint8)":{"details":"Triggered when the contract has been initialized or reinitialized."}},"kind":"dev","methods":{},"stateVariables":{"_initialized":{"custom:oz-retyped-from":"bool","details":"Indicates that the contract has been initialized."},"_initializing":{"details":"Indicates that the contract is in the process of being initialized."}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"}],\"devdoc\":{\"custom:oz-upgrades-unsafe-allow\":\"constructor constructor() {     _disableInitializers(); } ``` ====\",\"details\":\"This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. The initialization functions use a version number. Once a version number is used, it is consumed and cannot be reused. This mechanism prevents re-execution of each \\\"step\\\" but allows the creation of new initialization steps in case an upgrade adds a module that needs to be initialized. For example: [.hljs-theme-light.nopadding] ```solidity contract MyToken is ERC20Upgradeable {     function initialize() initializer public {         __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\");     } } contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {     function initializeV2() reinitializer(2) public {         __ERC20Permit_init(\\\"MyToken\\\");     } } ``` TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. [CAUTION] ==== Avoid leaving a contract uninitialized. An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: [.hljs-theme-light.nopadding] ```\",\"events\":{\"Initialized(uint8)\":{\"details\":\"Triggered when the contract has been initialized or reinitialized.\"}},\"kind\":\"dev\",\"methods\":{},\"stateVariables\":{\"_initialized\":{\"custom:oz-retyped-from\":\"bool\",\"details\":\"Indicates that the contract has been initialized.\"},\"_initializing\":{\"details\":\"Indicates that the contract is in the process of being initialized.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Origin.sol\":\"Initializable\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Origin.sol\":{\"keccak256\":\"0x96775924f147f3d1f8df8cdf56731fe52a15af8d8e12e608efb8158c112b18cd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e642a27f5fab3c62b4c02e9754e9e42b1cf2e5381dbea9d3d106d23b7772ebe6\",\"dweb:/ipfs/QmUwn7ZyBvPkjnMuK8ZMSexBUdNQnVtxwyoAyT4DXLQjra\"]}},\"version\":1}"},"hashes":{}},"solidity/Origin.sol:InterfaceGasOracle":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/OriginEvents.sol\n\n/// @notice A collection of events emitted by the Origin contract\nabstract contract OriginEvents {\n    /**\n     * @notice Emitted when a new message is sent.\n     * @param messageHash   Hash of message; the leaf inserted to the Merkle tree for the message\n     * @param nonce         Nonce of sent message (starts from 1)\n     * @param destination   Destination domain\n     * @param message       Raw bytes of message\n     */\n    event Sent(bytes32 indexed messageHash, uint32 indexed nonce, uint32 indexed destination, bytes message);\n\n    /**\n     * @notice Emitted when a tip withdrawal is completed.\n     * @param actor     Actor address\n     * @param tip       Tip value, denominated in local domain's wei\n     */\n    event TipWithdrawalCompleted(address actor, uint256 tip);\n}\n\n// contracts/events/StateHubEvents.sol\n\n/// @notice A collection of events emitted by the StateHub contract\nabstract contract StateHubEvents {\n    /**\n     * @notice Emitted when a new Origin State is saved after a message was sent.\n     * @param state     Raw payload with state data\n     */\n    event StateSaved(bytes state);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n    /**\n     * @notice Check that a given state is valid: matches the historical state of Origin contract.\n     * Note: any Agent including an invalid state in their snapshot will be slashed\n     * upon providing the snapshot and agent signature for it to Origin contract.\n     * @dev Will revert if any of these is true:\n     *  - State payload is not properly formatted.\n     * @param statePayload      Raw payload with state data\n     * @return isValid          Whether the provided state is valid\n     */\n    function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns the amount of saved states so far.\n     * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n     */\n    function statesAmount() external view returns (uint256);\n\n    /**\n     * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @return statePayload     Raw payload with the latest state data\n     */\n    function suggestLatestState() external view returns (bytes memory statePayload);\n\n    /**\n     * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @param nonce             Historical nonce to form a state\n     * @return statePayload     Raw payload with historical state data\n     */\n    function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/InterfaceGasOracle.sol\n\ninterface InterfaceGasOracle {\n    /**\n     * @notice Fetches the latest gas data for the chain from `Destination` contract,\n     * and uses it to update the oracle values for the requested chain.\n     * @param domain    Domain to update the gas data for\n     */\n    function updateGasData(uint32 domain) external;\n\n    /**\n     * @notice Returns the gas data for the local chain.\n     */\n    function getGasData() external view returns (uint256 paddedGasData);\n\n    /**\n     * @notice Returns the gas data for the given domain, in the decoded format.\n     * @param domain        Domain of chain to get gas data for\n     * @return gasPrice     Gas price for the chain (in Wei per gas unit)\n     * @return dataPrice    Calldata price (in Wei per byte of content)\n     * @return execBuffer   Tx fee safety buffer for message execution (in Wei)\n     * @return amortAttCost Amortized cost for attestation submission (in Wei)\n     * @return etherPrice   Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n     * @return markup       Markup for the message execution (in BWAD)\n     */\n    function getDecodedGasData(uint32 domain)\n        external\n        view\n        returns (\n            uint256 gasPrice,\n            uint256 dataPrice,\n            uint256 execBuffer,\n            uint256 amortAttCost,\n            uint256 etherPrice,\n            uint256 markup\n        );\n\n    /**\n     * @notice Returns the minimum tips for sending a message to a given destination.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return paddedTips       Padded encoded minimum tips information\n     */\n    function getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 paddedTips);\n}\n\n// contracts/interfaces/InterfaceOrigin.sol\n\ninterface InterfaceOrigin {\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /**\n     * @notice Send a message to the recipient located on destination domain.\n     * @dev Recipient has to conform to IMessageRecipient interface, otherwise message won't be delivered.\n     * Will revert if any of these is true:\n     * - `destination` is equal to contract's local domain\n     * - `content` length is greater than `MAX_CONTENT_BYTES`\n     * - `msg.value` is lower than value of minimum tips for the given message\n     * @param destination           Domain of destination chain\n     * @param recipient             Address of recipient on destination chain as bytes32\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param paddedRequest         Padded encoded message execution request on destination chain\n     * @param content               Raw bytes content of message\n     * @return messageNonce         Nonce of the sent message\n     * @return messageHash          Hash of the sent message\n     */\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable returns (uint32 messageNonce, bytes32 messageHash);\n\n    /**\n     * @notice Send a manager message to the destination domain.\n     * @dev This could only be called by AgentManager, which takes care of encoding the calldata payload.\n     * Note: (msgOrigin, proofMaturity) security args will be added to payload on the destination chain\n     * so that the AgentManager could verify where the Manager Message came from and how mature is the proof.\n     * Note: function is not payable, as no tips are required for sending a manager message.\n     * Will revert if `destination` is equal to contract's local domain.\n     * @param destination           Domain of destination chain\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param payload               Payload for calling AgentManager on destination chain (with extra security args)\n     */\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        returns (uint32 messageNonce, bytes32 messageHash);\n\n    // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Withdraws locked base message tips to the recipient.\n     * @dev Could only be called by a local AgentManager.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function withdrawTips(address recipient, uint256 amount) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the minimum tips value for sending a message to a given destination.\n     * @dev Using at least `tipsValue` as `msg.value` for `sendBaseMessage()`\n     * will guarantee that the message will be accepted.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return tipsValue        Minimum tips value for a message to be accepted\n     */\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue);\n}\n\n// contracts/libs/Constants.sol\n\n// Here we define common constants to enable their easier reusing later.\n\n// ══════════════════════════════════ MERKLE ═══════════════════════════════════\n/// @dev Height of the Agent Merkle Tree\nuint256 constant AGENT_TREE_HEIGHT = 32;\n/// @dev Height of the Origin Merkle Tree\nuint256 constant ORIGIN_TREE_HEIGHT = 32;\n/// @dev Height of the Snapshot Merkle Tree. Allows up to 64 leafs, e.g. up to 32 states\nuint256 constant SNAPSHOT_TREE_HEIGHT = 6;\n// ══════════════════════════════════ STRUCTS ══════════════════════════════════\n/// @dev See Attestation.sol: (bytes32,bytes32,uint32,uint40,uint40): 32+32+4+5+5\nuint256 constant ATTESTATION_LENGTH = 78;\n/// @dev See GasData.sol: (uint16,uint16,uint16,uint16,uint16,uint16): 2+2+2+2+2+2\nuint256 constant GAS_DATA_LENGTH = 12;\n/// @dev See Receipt.sol: (uint32,uint32,bytes32,bytes32,uint8,address,address,address): 4+4+32+32+1+20+20+20\nuint256 constant RECEIPT_LENGTH = 133;\n/// @dev See State.sol: (bytes32,uint32,uint32,uint40,uint40,GasData): 32+4+4+5+5+len(GasData)\nuint256 constant STATE_LENGTH = 50 + GAS_DATA_LENGTH;\n/// @dev Maximum amount of states in a single snapshot. Each state produces two leafs in the tree\nuint256 constant SNAPSHOT_MAX_STATES = 1 \u003c\u003c (SNAPSHOT_TREE_HEIGHT - 1);\n// ══════════════════════════════════ MESSAGE ══════════════════════════════════\n/// @dev See Header.sol: (uint8,uint32,uint32,uint32,uint32): 1+4+4+4+4\nuint256 constant HEADER_LENGTH = 17;\n/// @dev See Request.sol: (uint96,uint64,uint32): 12+8+4\nuint256 constant REQUEST_LENGTH = 24;\n/// @dev See Tips.sol: (uint64,uint64,uint64,uint64): 8+8+8+8\nuint256 constant TIPS_LENGTH = 32;\n/// @dev The amount of discarded last bits when encoding tip values\nuint256 constant TIPS_GRANULARITY = 32;\n/// @dev Tip values could be only the multiples of TIPS_MULTIPLIER\nuint256 constant TIPS_MULTIPLIER = 1 \u003c\u003c TIPS_GRANULARITY;\n// ══════════════════════════════ STATEMENT SALTS ══════════════════════════════\n/// @dev Salts for signing various statements\nbytes32 constant ATTESTATION_VALID_SALT = keccak256(\"ATTESTATION_VALID_SALT\");\nbytes32 constant ATTESTATION_INVALID_SALT = keccak256(\"ATTESTATION_INVALID_SALT\");\nbytes32 constant RECEIPT_VALID_SALT = keccak256(\"RECEIPT_VALID_SALT\");\nbytes32 constant RECEIPT_INVALID_SALT = keccak256(\"RECEIPT_INVALID_SALT\");\nbytes32 constant SNAPSHOT_VALID_SALT = keccak256(\"SNAPSHOT_VALID_SALT\");\nbytes32 constant STATE_INVALID_SALT = keccak256(\"STATE_INVALID_SALT\");\n// ═════════════════════════════════ PROTOCOL ══════════════════════════════════\n/// @dev Optimistic period for new agent roots in LightManager\nuint32 constant AGENT_ROOT_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Timeout between the agent root could be proposed and resolved in LightManager\nuint32 constant AGENT_ROOT_PROPOSAL_TIMEOUT = 12 hours;\nuint32 constant BONDING_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Amount of time that the Notary will not be considered active after they won a dispute\nuint32 constant DISPUTE_TIMEOUT_NOTARY = 12 hours;\n/// @dev Amount of time without fresh data from Notaries before contract owner can resolve stuck disputes manually\nuint256 constant FRESH_DATA_TIMEOUT = 4 hours;\n/// @dev Maximum bytes per message = 2 KiB (somewhat arbitrarily set to begin)\nuint256 constant MAX_CONTENT_BYTES = 2 * 2 ** 10;\n/// @dev Maximum value for the summit tip that could be set in GasOracle\nuint256 constant MAX_SUMMIT_TIP = 0.01 ether;\n\n// contracts/libs/Errors.sol\n\n// ══════════════════════════════ INVALID CALLER ═══════════════════════════════\n\nerror CallerNotAgentManager();\nerror CallerNotDestination();\nerror CallerNotInbox();\nerror CallerNotSummit();\n\n// ══════════════════════════════ INCORRECT DATA ═══════════════════════════════\n\nerror IncorrectAttestation();\nerror IncorrectAgentDomain();\nerror IncorrectAgentIndex();\nerror IncorrectAgentProof();\nerror IncorrectAgentRoot();\nerror IncorrectDataHash();\nerror IncorrectDestinationDomain();\nerror IncorrectOriginDomain();\nerror IncorrectSnapshotProof();\nerror IncorrectSnapshotRoot();\nerror IncorrectState();\nerror IncorrectStatesAmount();\nerror IncorrectTipsProof();\nerror IncorrectVersionLength();\n\nerror IncorrectNonce();\nerror IncorrectSender();\nerror IncorrectRecipient();\n\nerror FlagOutOfRange();\nerror IndexOutOfRange();\nerror NonceOutOfRange();\n\nerror OutdatedNonce();\n\nerror UnformattedAttestation();\nerror UnformattedAttestationReport();\nerror UnformattedBaseMessage();\nerror UnformattedCallData();\nerror UnformattedCallDataPrefix();\nerror UnformattedMessage();\nerror UnformattedReceipt();\nerror UnformattedReceiptReport();\nerror UnformattedSignature();\nerror UnformattedSnapshot();\nerror UnformattedState();\nerror UnformattedStateReport();\n\n// ═══════════════════════════════ MERKLE TREES ════════════════════════════════\n\nerror LeafNotProven();\nerror MerkleTreeFull();\nerror NotEnoughLeafs();\nerror TreeHeightTooLow();\n\n// ═════════════════════════════ OPTIMISTIC PERIOD ═════════════════════════════\n\nerror BaseClientOptimisticPeriod();\nerror MessageOptimisticPeriod();\nerror SlashAgentOptimisticPeriod();\nerror WithdrawTipsOptimisticPeriod();\nerror ZeroProofMaturity();\n\n// ═══════════════════════════════ AGENT MANAGER ═══════════════════════════════\n\nerror AgentNotGuard();\nerror AgentNotNotary();\n\nerror AgentCantBeAdded();\nerror AgentNotActive();\nerror AgentNotActiveNorUnstaking();\nerror AgentNotFraudulent();\nerror AgentNotUnstaking();\nerror AgentUnknown();\n\nerror AgentRootNotProposed();\nerror AgentRootTimeoutNotOver();\n\nerror NotStuck();\n\nerror DisputeAlreadyResolved();\nerror DisputeNotOpened();\nerror DisputeTimeoutNotOver();\nerror GuardInDispute();\nerror NotaryInDispute();\n\nerror MustBeSynapseDomain();\nerror SynapseDomainForbidden();\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\nerror AlreadyExecuted();\nerror AlreadyFailed();\nerror DuplicatedSnapshotRoot();\nerror IncorrectMagicValue();\nerror GasLimitTooLow();\nerror GasSuppliedTooLow();\n\n// ══════════════════════════════════ ORIGIN ═══════════════════════════════════\n\nerror ContentLengthTooBig();\nerror EthTransferFailed();\nerror InsufficientEthBalance();\n\n// ════════════════════════════════ GAS ORACLE ═════════════════════════════════\n\nerror LocalGasDataNotSet();\nerror RemoteGasDataNotSet();\n\n// ═══════════════════════════════════ TIPS ════════════════════════════════════\n\nerror SummitTipTooHigh();\nerror TipsClaimMoreThanEarned();\nerror TipsClaimZero();\nerror TipsOverflow();\nerror TipsValueTooLow();\n\n// ════════════════════════════════ MEMORY VIEW ════════════════════════════════\n\nerror IndexedTooMuch();\nerror ViewOverrun();\nerror OccupiedMemory();\nerror UnallocatedMemory();\nerror PrecompileOutOfGas();\n\n// ═════════════════════════════════ MULTICALL ═════════════════════════════════\n\nerror MulticallFailed();\n\n// contracts/libs/TypeCasts.sol\n\nlibrary TypeCasts {\n    // alignment preserving cast\n    function addressToBytes32(address addr) internal pure returns (bytes32) {\n        return bytes32(uint256(uint160(addr)));\n    }\n\n    // alignment preserving cast\n    function bytes32ToAddress(bytes32 buf) internal pure returns (address) {\n        return address(uint160(uint256(buf)));\n    }\n}\n\n// contracts/libs/stack/Number.sol\n\n/// Number is a compact representation of uint256, that is fit into 16 bits\n/// with the maximum relative error under 0.4%.\ntype Number is uint16;\n\nusing NumberLib for Number global;\n\n/// # Number\n/// Library for compact representation of uint256 numbers.\n/// - Number is stored using mantissa and exponent, each occupying 8 bits.\n/// - Numbers under 2**8 are stored as `mantissa` with `exponent = 0xFF`.\n/// - Numbers at least 2**8 are approximated as `(256 + mantissa) \u003c\u003c exponent`\n/// \u003e - `0 \u003c= mantissa \u003c 256`\n/// \u003e - `0 \u003c= exponent \u003c= 247` (`256 * 2**248` doesn't fit into uint256)\n/// # Number stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type  | Bytes |\n/// | ---------- | -------- | ----- | ----- |\n/// | (002..001] | mantissa | uint8 | 1     |\n/// | (001..000] | exponent | uint8 | 1     |\n\nlibrary NumberLib {\n    /// @dev Amount of bits to shift to mantissa field\n    uint16 private constant SHIFT_MANTISSA = 8;\n\n    /// @notice For bwad math (binary wad) we use 2**64 as \"wad\" unit.\n    /// @dev We are using not using 10**18 as wad, because it is not stored precisely in NumberLib.\n    uint256 internal constant BWAD_SHIFT = 64;\n    uint256 internal constant BWAD = 1 \u003c\u003c BWAD_SHIFT;\n    /// @notice ~0.1% in bwad units.\n    uint256 internal constant PER_MILLE_SHIFT = BWAD_SHIFT - 10;\n    uint256 internal constant PER_MILLE = 1 \u003c\u003c PER_MILLE_SHIFT;\n\n    /// @notice Compresses uint256 number into 16 bits.\n    function compress(uint256 value) internal pure returns (Number) {\n        // Find `msb` such as `2**msb \u003c= value \u003c 2**(msb + 1)`\n        uint256 msb = mostSignificantBit(value);\n        // We want to preserve 9 bits of precision.\n        // The highest bit is always 1, so we can skip it.\n        // The remaining 8 highest bits are stored as mantissa.\n        if (msb \u003c 8) {\n            // Value is less than 2**8, so we can use value as mantissa with \"-1\" exponent.\n            return _encode(uint8(value), 0xFF);\n        } else {\n            // We use `msb - 8` as exponent otherwise. Note that `exponent \u003e= 0`.\n            unchecked {\n                uint256 exponent = msb - 8;\n                // Shifting right by `msb-8` bits will shift the \"remaining 8 highest bits\" into the 8 lowest bits.\n                // uint8() will truncate the highest bit.\n                return _encode(uint8(value \u003e\u003e exponent), uint8(exponent));\n            }\n        }\n    }\n\n    /// @notice Decompresses 16 bits number into uint256.\n    /// @dev The outcome is an approximation of the original number: `(value - value / 256) \u003c number \u003c= value`.\n    function decompress(Number number) internal pure returns (uint256 value) {\n        // Isolate 8 highest bits as the mantissa.\n        uint256 mantissa = Number.unwrap(number) \u003e\u003e SHIFT_MANTISSA;\n        // This will truncate the highest bits, leaving only the exponent.\n        uint256 exponent = uint8(Number.unwrap(number));\n        if (exponent == 0xFF) {\n            return mantissa;\n        } else {\n            unchecked {\n                return (256 + mantissa) \u003c\u003c (exponent);\n            }\n        }\n    }\n\n    /// @dev Returns the most significant bit of `x`\n    /// https://solidity-by-example.org/bitwise/\n    function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\n        // To find `msb` we determine it bit by bit, starting from the highest one.\n        // `0 \u003c= msb \u003c= 255`, so we start from the highest bit, 1\u003c\u003c7 == 128.\n        // If `x` is at least 2**128, then the highest bit of `x` is at least 128.\n        // solhint-disable no-inline-assembly\n        assembly {\n            // `f` is set to 1\u003c\u003c7 if `x \u003e= 2**128` and to 0 otherwise.\n            let f := shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\n            // If `x \u003e= 2**128` then set `msb` highest bit to 1 and shift `x` right by 128.\n            // Otherwise, `msb` remains 0 and `x` remains unchanged.\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        // `x` is now at most 2**128 - 1. Continue the same way, the next highest bit is 1\u003c\u003c6 == 64.\n        assembly {\n            // `f` is set to 1\u003c\u003c6 if `x \u003e= 2**64` and to 0 otherwise.\n            let f := shl(6, gt(x, 0xFFFFFFFFFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c5 if `x \u003e= 2**32` and to 0 otherwise.\n            let f := shl(5, gt(x, 0xFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c4 if `x \u003e= 2**16` and to 0 otherwise.\n            let f := shl(4, gt(x, 0xFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c3 if `x \u003e= 2**8` and to 0 otherwise.\n            let f := shl(3, gt(x, 0xFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c2 if `x \u003e= 2**4` and to 0 otherwise.\n            let f := shl(2, gt(x, 0xF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c1 if `x \u003e= 2**2` and to 0 otherwise.\n            let f := shl(1, gt(x, 0x3))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1 if `x \u003e= 2**1` and to 0 otherwise.\n            let f := gt(x, 0x1)\n            msb := or(msb, f)\n        }\n    }\n\n    /// @dev Wraps (mantissa, exponent) pair into Number.\n    function _encode(uint8 mantissa, uint8 exponent) private pure returns (Number) {\n        // Casts below are upcasts, so they are safe.\n        return Number.wrap(uint16(mantissa) \u003c\u003c SHIFT_MANTISSA | uint16(exponent));\n    }\n}\n\n// contracts/libs/stack/Request.sol\n\n/// Request is encoded data with \"message execution request\".\ntype Request is uint192;\n\nusing RequestLib for Request global;\n\n/// Library for formatting _the request part_ of _the base messages_.\n/// - Request represents a message sender requirements for the message execution on the destination chain.\n/// - Request occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n/// \u003e gasDrop field is included for future compatibility and is ignored at the moment.\n///\n/// # Request stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type   | Bytes | Description                                          |\n/// | ---------- | -------- | ------ | ----- | ---------------------------------------------------- |\n/// | (024..012] | gasDrop  | uint96 | 12    | Minimum amount of gas token to drop to the recipient |\n/// | (012..004] | gasLimit | uint64 | 8     | Minimum amount of gas units to supply for execution  |\n/// | (004..000] | version  | uint32 | 4     | Base message version to pass to the recipient        |\n\nlibrary RequestLib {\n    /// @dev Amount of bits to shift to gasDrop field\n    uint192 private constant SHIFT_GAS_DROP = 12 * 8;\n    /// @dev Amount of bits to shift to gasLimit field\n    uint192 private constant SHIFT_GAS_LIMIT = 4 * 8;\n\n    /// @notice Returns an encoded request with the given fields\n    /// @param gasDrop_     Minimum amount of gas token to drop to the recipient (ignored at the moment)\n    /// @param gasLimit_    Minimum amount of gas units to supply for execution\n    /// @param version_     Base message version to pass to the recipient\n    function encodeRequest(uint96 gasDrop_, uint64 gasLimit_, uint32 version_) internal pure returns (Request) {\n        // Casts below are upcasts, so they are safe\n        return Request.wrap(uint192(gasDrop_) \u003c\u003c SHIFT_GAS_DROP | uint192(gasLimit_) \u003c\u003c SHIFT_GAS_LIMIT | version_);\n    }\n\n    /// @notice Wraps the padded encoded request into a Request-typed value.\n    /// @dev The \"padded\" request is simply an encoded request casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded requests\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedRequest) internal pure returns (Request) {\n        // Casting to uint192 will truncate the highest bits, which is the behavior we want\n        return Request.wrap(uint192(paddedRequest));\n    }\n\n    /// @notice Returns the requested of gas token to drop to the recipient.\n    function gasDrop(Request request) internal pure returns (uint96) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return uint96(Request.unwrap(request) \u003e\u003e SHIFT_GAS_DROP);\n    }\n\n    /// @notice Returns the requested minimum amount of gas units to supply for execution.\n    function gasLimit(Request request) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Request.unwrap(request) \u003e\u003e SHIFT_GAS_LIMIT);\n    }\n\n    /// @notice Returns the requested base message version to pass to the recipient.\n    function version(Request request) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Request.unwrap(request));\n    }\n}\n\n// node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        require(value \u003c= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        require(value \u003c= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        require(value \u003c= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value \u003c= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        require(value \u003c= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        require(value \u003c= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        require(value \u003c= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        require(value \u003c= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        require(value \u003c= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        require(value \u003c= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        require(value \u003c= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        require(value \u003c= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        require(value \u003c= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        require(value \u003c= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        require(value \u003c= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value \u003c= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        require(value \u003c= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        require(value \u003c= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        require(value \u003c= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value \u003c= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        require(value \u003c= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        require(value \u003c= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        require(value \u003c= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value \u003c= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        require(value \u003c= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        require(value \u003c= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        require(value \u003c= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value \u003c= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        require(value \u003c= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value \u003c= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value \u003c= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     *\n     * _Available since v3.0._\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value \u003e= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     *\n     * _Available since v3.0._\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value \u003c= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     *\n     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length \u003e 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance \u003e= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance \u003e= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length \u003e 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n\n// contracts/base/MultiCallable.sol\n\n/// @notice Collection of Multicall utilities. Fork of Multicall3:\n/// https://github.com/mds1/multicall/blob/master/src/Multicall3.sol\nabstract contract MultiCallable {\n    struct Call {\n        bool allowFailure;\n        bytes callData;\n    }\n\n    struct Result {\n        bool success;\n        bytes returnData;\n    }\n\n    /// @notice Aggregates a few calls to this contract into one multicall without modifying `msg.sender`.\n    function multicall(Call[] calldata calls) external returns (Result[] memory callResults) {\n        uint256 amount = calls.length;\n        callResults = new Result[](amount);\n        Call calldata call_;\n        for (uint256 i = 0; i \u003c amount;) {\n            call_ = calls[i];\n            Result memory result = callResults[i];\n            // We perform a delegate call to ourselves here. Delegate call does not modify `msg.sender`, so\n            // this will have the same effect as if `msg.sender` performed all the calls themselves one by one.\n            // solhint-disable-next-line avoid-low-level-calls\n            (result.success, result.returnData) = address(this).delegatecall(call_.callData);\n            // solhint-disable-next-line no-inline-assembly\n            assembly {\n                // Revert if the call fails and failure is not allowed\n                // `allowFailure := calldataload(call_)` and `success := mload(result)`\n                if iszero(or(calldataload(call_), mload(result))) {\n                    // Revert with `0x4d6a2328` (function selector for `MulticallFailed()`)\n                    mstore(0x00, 0x4d6a232800000000000000000000000000000000000000000000000000000000)\n                    revert(0x00, 0x04)\n                }\n            }\n            unchecked {\n                ++i;\n            }\n        }\n    }\n}\n\n// contracts/base/Version.sol\n\n/**\n * @title Versioned\n * @notice Version getter for contracts. Doesn't use any storage slots, meaning\n * it will never cause any troubles with the upgradeable contracts. For instance, this contract\n * can be added or removed from the inheritance chain without shifting the storage layout.\n */\nabstract contract Versioned {\n    /**\n     * @notice Struct that is mimicking the storage layout of a string with 32 bytes or less.\n     * Length is limited by 32, so the whole string payload takes two memory words:\n     * @param length    String length\n     * @param data      String characters\n     */\n    struct _ShortString {\n        uint256 length;\n        bytes32 data;\n    }\n\n    /// @dev Length of the \"version string\"\n    uint256 private immutable _length;\n    /// @dev Bytes representation of the \"version string\".\n    /// Strings with length over 32 are not supported!\n    bytes32 private immutable _data;\n\n    constructor(string memory version_) {\n        _length = bytes(version_).length;\n        if (_length \u003e 32) revert IncorrectVersionLength();\n        // bytes32 is left-aligned =\u003e this will store the byte representation of the string\n        // with the trailing zeroes to complete the 32-byte word\n        _data = bytes32(bytes(version_));\n    }\n\n    function version() external view returns (string memory versionString) {\n        // Load the immutable values to form the version string\n        _ShortString memory str = _ShortString(_length, _data);\n        // The only way to do this cast is doing some dirty assembly\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            versionString := str\n        }\n    }\n}\n\n// contracts/libs/ChainContext.sol\n\n/// @notice Library for accessing chain context variables as tightly packed integers.\n/// Messaging contracts should rely on this library for accessing chain context variables\n/// instead of doing the casting themselves.\nlibrary ChainContext {\n    using SafeCast for uint256;\n\n    /// @notice Returns the current block number as uint40.\n    /// @dev Reverts if block number is greater than 40 bits, which is not supposed to happen\n    /// until the block.timestamp overflows (assuming block time is at least 1 second).\n    function blockNumber() internal view returns (uint40) {\n        return block.number.toUint40();\n    }\n\n    /// @notice Returns the current block timestamp as uint40.\n    /// @dev Reverts if block timestamp is greater than 40 bits, which is\n    /// supposed to happen approximately in year 36835.\n    function blockTimestamp() internal view returns (uint40) {\n        return block.timestamp.toUint40();\n    }\n\n    /// @notice Returns the chain id as uint32.\n    /// @dev Reverts if chain id is greater than 32 bits, which is not\n    /// supposed to happen in production.\n    function chainId() internal view returns (uint32) {\n        return block.chainid.toUint32();\n    }\n}\n\n// contracts/libs/Structures.sol\n\n// Here we define common enums and structures to enable their easier reusing later.\n\n// ═══════════════════════════════ AGENT STATUS ════════════════════════════════\n\n/// @dev Potential statuses for the off-chain bonded agent:\n/// - Unknown: never provided a bond =\u003e signature not valid\n/// - Active: has a bond in BondingManager =\u003e signature valid\n/// - Unstaking: has a bond in BondingManager, initiated the unstaking =\u003e signature not valid\n/// - Resting: used to have a bond in BondingManager, successfully unstaked =\u003e signature not valid\n/// - Fraudulent: proven to commit fraud, value in Merkle Tree not updated =\u003e signature not valid\n/// - Slashed: proven to commit fraud, value in Merkle Tree was updated =\u003e signature not valid\n/// Unstaked agent could later be added back to THE SAME domain by staking a bond again.\n/// Honest agent: Unknown -\u003e Active -\u003e unstaking -\u003e Resting -\u003e Active ...\n/// Malicious agent: Unknown -\u003e Active -\u003e Fraudulent -\u003e Slashed\n/// Malicious agent: Unknown -\u003e Active -\u003e Unstaking -\u003e Fraudulent -\u003e Slashed\nenum AgentFlag {\n    Unknown,\n    Active,\n    Unstaking,\n    Resting,\n    Fraudulent,\n    Slashed\n}\n\n/// @notice Struct for storing an agent in the BondingManager contract.\nstruct AgentStatus {\n    AgentFlag flag;\n    uint32 domain;\n    uint32 index;\n}\n// 184 bits available for tight packing\n\nusing StructureUtils for AgentStatus global;\n\n/// @notice Potential statuses of an agent in terms of being in dispute\n/// - None: agent is not in dispute\n/// - Pending: agent is in unresolved dispute\n/// - Slashed: agent was in dispute that lead to agent being slashed\n/// Note: agent who won the dispute has their status reset to None\nenum DisputeFlag {\n    None,\n    Pending,\n    Slashed\n}\n\n/// @notice Struct for storing dispute status of an agent.\n/// @param flag         Dispute flag: None/Pending/Slashed.\n/// @param openedAt     Timestamp when the latest agent dispute was opened (zero if not opened).\n/// @param resolvedAt   Timestamp when the latest agent dispute was resolved (zero if not resolved).\nstruct DisputeStatus {\n    DisputeFlag flag;\n    uint40 openedAt;\n    uint40 resolvedAt;\n}\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\n/// @notice Struct representing the status of Destination contract.\n/// @param snapRootTime     Timestamp when latest snapshot root was accepted\n/// @param agentRootTime    Timestamp when latest agent root was accepted\n/// @param notaryIndex      Index of Notary who signed the latest agent root\nstruct DestinationStatus {\n    uint40 snapRootTime;\n    uint40 agentRootTime;\n    uint32 notaryIndex;\n}\n\n// ═══════════════════════════════ EXECUTION HUB ═══════════════════════════════\n\n/// @notice Potential statuses of the message in Execution Hub.\n/// - None: there hasn't been a valid attempt to execute the message yet\n/// - Failed: there was a valid attempt to execute the message, but recipient reverted\n/// - Success: there was a valid attempt to execute the message, and recipient did not revert\n/// Note: message can be executed until its status is Success\nenum MessageStatus {\n    None,\n    Failed,\n    Success\n}\n\nlibrary StructureUtils {\n    /// @notice Checks that Agent is Active\n    function verifyActive(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active) {\n            revert AgentNotActive();\n        }\n    }\n\n    /// @notice Checks that Agent is Unstaking\n    function verifyUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Unstaking) {\n            revert AgentNotUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Active or Unstaking\n    function verifyActiveUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active \u0026\u0026 status.flag != AgentFlag.Unstaking) {\n            revert AgentNotActiveNorUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Fraudulent\n    function verifyFraudulent(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Fraudulent) {\n            revert AgentNotFraudulent();\n        }\n    }\n\n    /// @notice Checks that Agent is not Unknown\n    function verifyKnown(AgentStatus memory status) internal pure {\n        if (status.flag == AgentFlag.Unknown) {\n            revert AgentUnknown();\n        }\n    }\n}\n\n// contracts/libs/memory/MemView.sol\n\n/// @dev MemView is an untyped view over a portion of memory to be used instead of `bytes memory`\ntype MemView is uint256;\n\n/// @dev Attach library functions to MemView\nusing MemViewLib for MemView global;\n\n/// @notice Library for operations with the memory views.\n/// Forked from https://github.com/summa-tx/memview-sol with several breaking changes:\n/// - The codebase is ported to Solidity 0.8\n/// - Custom errors are added\n/// - The runtime type checking is replaced with compile-time check provided by User-Defined Value Types\n///   https://docs.soliditylang.org/en/latest/types.html#user-defined-value-types\n/// - uint256 is used as the underlying type for the \"memory view\" instead of bytes29.\n///   It is wrapped into MemView custom type in order not to be confused with actual integers.\n/// - Therefore the \"type\" field is discarded, allowing to allocate 16 bytes for both view location and length\n/// - The documentation is expanded\n/// - Library functions unused by the rest of the codebase are removed\n//  - Very pretty code separators are added :)\nlibrary MemViewLib {\n    /// @notice Stack layout for uint256 (from highest bits to lowest)\n    /// (32 .. 16]      loc     16 bytes    Memory address of underlying bytes\n    /// (16 .. 00]      len     16 bytes    Length of underlying bytes\n\n    // ═══════════════════════════════════════════ BUILDING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Instantiate a new untyped memory view. This should generally not be called directly.\n     * Prefer `ref` wherever possible.\n     * @param loc_          The memory address\n     * @param len_          The length\n     * @return The new view with the specified location and length\n     */\n    function build(uint256 loc_, uint256 len_) internal pure returns (MemView) {\n        uint256 end_ = loc_ + len_;\n        // Make sure that a view is not constructed that points to unallocated memory\n        // as this could be indicative of a buffer overflow attack\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            if gt(end_, mload(0x40)) { end_ := 0 }\n        }\n        if (end_ == 0) {\n            revert UnallocatedMemory();\n        }\n        return _unsafeBuildUnchecked(loc_, len_);\n    }\n\n    /**\n     * @notice Instantiate a memory view from a byte array.\n     * @dev Note that due to Solidity memory representation, it is not possible to\n     * implement a deref, as the `bytes` type stores its len in memory.\n     * @param arr           The byte array\n     * @return The memory view over the provided byte array\n     */\n    function ref(bytes memory arr) internal pure returns (MemView) {\n        uint256 len_ = arr.length;\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 loc_;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // We add 0x20, so that the view starts exactly where the array data starts\n            loc_ := add(arr, 0x20)\n        }\n        return build(loc_, len_);\n    }\n\n    // ════════════════════════════════════════════ CLONING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to the new memory.\n     * @param memView       The memory view\n     * @return arr          The cloned byte array\n     */\n    function clone(MemView memView) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        unchecked {\n            _unsafeCopyTo(memView, ptr + 0x20);\n        }\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 len_ = memView.len();\n        uint256 footprint_ = memView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    /**\n     * @notice Copies all views, joins them into a new bytearray.\n     * @param memViews      The memory views\n     * @return arr          The new byte array with joined data behind the given views\n     */\n    function join(MemView[] memory memViews) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        MemView newView;\n        unchecked {\n            newView = _unsafeJoin(memViews, ptr + 0x20);\n        }\n        uint256 len_ = newView.len();\n        uint256 footprint_ = newView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    // ══════════════════════════════════════════ INSPECTING MEMORY VIEW ═══════════════════════════════════════════════\n\n    /**\n     * @notice Returns the memory address of the underlying bytes.\n     * @param memView       The memory view\n     * @return loc_         The memory address\n     */\n    function loc(MemView memView) internal pure returns (uint256 loc_) {\n        // loc is stored in the highest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u003e\u003e 128;\n    }\n\n    /**\n     * @notice Returns the number of bytes of the view.\n     * @param memView       The memory view\n     * @return len_         The length of the view\n     */\n    function len(MemView memView) internal pure returns (uint256 len_) {\n        // len is stored in the lowest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u0026 type(uint128).max;\n    }\n\n    /**\n     * @notice Returns the endpoint of `memView`.\n     * @param memView       The memory view\n     * @return end_         The endpoint of `memView`\n     */\n    function end(MemView memView) internal pure returns (uint256 end_) {\n        // The endpoint never overflows uint128, let alone uint256, so we could use unchecked math here\n        unchecked {\n            return memView.loc() + memView.len();\n        }\n    }\n\n    /**\n     * @notice Returns the number of memory words this memory view occupies, rounded up.\n     * @param memView       The memory view\n     * @return words_       The number of memory words\n     */\n    function words(MemView memView) internal pure returns (uint256 words_) {\n        // returning ceil(length / 32.0)\n        unchecked {\n            return (memView.len() + 31) \u003e\u003e 5;\n        }\n    }\n\n    /**\n     * @notice Returns the in-memory footprint of a fresh copy of the view.\n     * @param memView       The memory view\n     * @return footprint_   The in-memory footprint of a fresh copy of the view.\n     */\n    function footprint(MemView memView) internal pure returns (uint256 footprint_) {\n        // words() * 32\n        return memView.words() \u003c\u003c 5;\n    }\n\n    // ════════════════════════════════════════════ HASHING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the keccak256 hash of the underlying memory\n     * @param memView       The memory view\n     * @return digest       The keccak256 hash of the underlying memory\n     */\n    function keccak(MemView memView) internal pure returns (bytes32 digest) {\n        uint256 loc_ = memView.loc();\n        uint256 len_ = memView.len();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            digest := keccak256(loc_, len_)\n        }\n    }\n\n    /**\n     * @notice Adds a salt to the keccak256 hash of the underlying data and returns the keccak256 hash of the\n     * resulting data.\n     * @param memView       The memory view\n     * @return digestSalted keccak256(salt, keccak256(memView))\n     */\n    function keccakSalted(MemView memView, bytes32 salt) internal pure returns (bytes32 digestSalted) {\n        return keccak256(bytes.concat(salt, memView.keccak()));\n    }\n\n    // ════════════════════════════════════════════ SLICING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Safe slicing without memory modification.\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the given index\n     */\n    function slice(MemView memView, uint256 index_, uint256 len_) internal pure returns (MemView) {\n        uint256 loc_ = memView.loc();\n        // Ensure it doesn't overrun the view\n        if (loc_ + index_ + len_ \u003e memView.end()) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // loc_ + index_ \u003c= memView.end()\n            return build({loc_: loc_ + index_, len_: len_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing bytes from `index` to end(memView).\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @return The new view for the slice starting from the given index until the initial view endpoint\n     */\n    function sliceFrom(MemView memView, uint256 index_) internal pure returns (MemView) {\n        uint256 len_ = memView.len();\n        // Ensure it doesn't overrun the view\n        if (index_ \u003e len_) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // index_ \u003c= len_ =\u003e memView.loc() + index_ \u003c= memView.loc() + memView.len() == memView.end()\n            return build({loc_: memView.loc() + index_, len_: len_ - index_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the first `len` bytes.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the initial view beginning\n     */\n    function prefix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        return memView.slice({index_: 0, len_: len_});\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the last `len` byte.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length until the initial view endpoint\n     */\n    function postfix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        uint256 viewLen = memView.len();\n        // Ensure it doesn't overrun the view\n        if (len_ \u003e viewLen) {\n            revert ViewOverrun();\n        }\n        // Could do the unchecked math due to the check above\n        uint256 index_;\n        unchecked {\n            index_ = viewLen - len_;\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // len_ \u003c= memView.len() =\u003e memView.loc() \u003c= loc_ \u003c= memView.end()\n            return build({loc_: memView.loc() + viewLen - len_, len_: len_});\n        }\n    }\n\n    // ═══════════════════════════════════════════ INDEXING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Load up to 32 bytes from the view onto the stack.\n     * @dev Returns a bytes32 with only the `bytes_` HIGHEST bytes set.\n     * This can be immediately cast to a smaller fixed-length byte array.\n     * To automatically cast to an integer, use `indexUint`.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return result       The 32 byte result having only `bytes_` highest bytes set\n     */\n    function index(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (bytes32 result) {\n        if (bytes_ == 0) {\n            return bytes32(0);\n        }\n        // Can't load more than 32 bytes to the stack in one go\n        if (bytes_ \u003e 32) {\n            revert IndexedTooMuch();\n        }\n        // The last indexed byte should be within view boundaries\n        if (index_ + bytes_ \u003e memView.len()) {\n            revert ViewOverrun();\n        }\n        uint256 bitLength = bytes_ \u003c\u003c 3; // bytes_ * 8\n        uint256 loc_ = memView.loc();\n        // Get a mask with `bitLength` highest bits set\n        uint256 mask;\n        // 0x800...00 binary representation is 100...00\n        // sar stands for \"signed arithmetic shift\": https://en.wikipedia.org/wiki/Arithmetic_shift\n        // sar(N-1, 100...00) = 11...100..00, with exactly N highest bits set to 1\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            mask := sar(sub(bitLength, 1), 0x8000000000000000000000000000000000000000000000000000000000000000)\n        }\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load a full word using index offset, and apply mask to ignore non-relevant bytes\n            result := and(mload(add(loc_, index_)), mask)\n        }\n    }\n\n    /**\n     * @notice Parse an unsigned integer from the view at `index`.\n     * @dev Requires that the view have \u003e= `bytes_` bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return The unsigned integer\n     */\n    function indexUint(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (uint256) {\n        bytes32 indexedBytes = memView.index(index_, bytes_);\n        // `index()` returns left-aligned `bytes_`, while integers are right-aligned\n        // Shifting here to right-align with the full 32 bytes word: need to shift right `(32 - bytes_)` bytes\n        unchecked {\n            // memView.index() reverts when bytes_ \u003e 32, thus unchecked math\n            return uint256(indexedBytes) \u003e\u003e ((32 - bytes_) \u003c\u003c 3);\n        }\n    }\n\n    /**\n     * @notice Parse an address from the view at `index`.\n     * @dev Requires that the view have \u003e= 20 bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @return The address\n     */\n    function indexAddress(MemView memView, uint256 index_) internal pure returns (address) {\n        // index 20 bytes as `uint160`, and then cast to `address`\n        return address(uint160(memView.indexUint(index_, 20)));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns a memory view over the specified memory location\n    /// without checking if it points to unallocated memory.\n    function _unsafeBuildUnchecked(uint256 loc_, uint256 len_) private pure returns (MemView) {\n        // There is no scenario where loc or len would overflow uint128, so we omit this check.\n        // We use the highest 128 bits to encode the location and the lowest 128 bits to encode the length.\n        return MemView.wrap((loc_ \u003c\u003c 128) | len_);\n    }\n\n    /**\n     * @notice Copy the view to a location, return an unsafe memory reference\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memView       The memory view\n     * @param newLoc        The new location to copy the underlying view data\n     * @return The memory view over the unsafe memory with the copied underlying data\n     */\n    function _unsafeCopyTo(MemView memView, uint256 newLoc) private view returns (MemView) {\n        uint256 len_ = memView.len();\n        uint256 oldLoc = memView.loc();\n\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (newLoc \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        bool res;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // use the identity precompile (0x04) to copy\n            res := staticcall(gas(), 0x04, oldLoc, len_, newLoc, len_)\n        }\n        if (!res) revert PrecompileOutOfGas();\n        return _unsafeBuildUnchecked({loc_: newLoc, len_: len_});\n    }\n\n    /**\n     * @notice Join the views in memory, return an unsafe reference to the memory.\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memViews      The memory views\n     * @return The conjoined view pointing to the new memory\n     */\n    function _unsafeJoin(MemView[] memory memViews, uint256 location) private view returns (MemView) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (location \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        // Copy the views to the specified location one by one, by tracking the amount of copied bytes so far\n        uint256 offset = 0;\n        for (uint256 i = 0; i \u003c memViews.length;) {\n            MemView memView = memViews[i];\n            // We can use the unchecked math here as location + sum(view.length) will never overflow uint256\n            unchecked {\n                _unsafeCopyTo(memView, location + offset);\n                offset += memView.len();\n                ++i;\n            }\n        }\n        return _unsafeBuildUnchecked({loc_: location, len_: offset});\n    }\n}\n\n// contracts/libs/merkle/MerkleMath.sol\n\nlibrary MerkleMath {\n    // ═════════════════════════════════════════ BASIC MERKLE CALCULATIONS ═════════════════════════════════════════════\n\n    /**\n     * @notice Calculates the merkle root for the given leaf and merkle proof.\n     * @dev Will revert if proof length exceeds the tree height.\n     * @param index     Index of `leaf` in tree\n     * @param leaf      Leaf of the merkle tree\n     * @param proof     Proof of inclusion of `leaf` in the tree\n     * @param height    Height of the merkle tree\n     * @return root_    Calculated Merkle Root\n     */\n    function proofRoot(uint256 index, bytes32 leaf, bytes32[] memory proof, uint256 height)\n        internal\n        pure\n        returns (bytes32 root_)\n    {\n        // Proof length could not exceed the tree height\n        uint256 proofLen = proof.length;\n        if (proofLen \u003e height) revert TreeHeightTooLow();\n        root_ = leaf;\n        /// @dev Apply unchecked to all ++h operations\n        unchecked {\n            // Go up the tree levels from the leaf following the proof\n            for (uint256 h = 0; h \u003c proofLen; ++h) {\n                // Get a sibling node on current level: this is proof[h]\n                root_ = getParent(root_, proof[h], index, h);\n            }\n            // Go up to the root: the remaining siblings are EMPTY\n            for (uint256 h = proofLen; h \u003c height; ++h) {\n                root_ = getParent(root_, bytes32(0), index, h);\n            }\n        }\n    }\n\n    /**\n     * @notice Calculates the parent of a node on the path from one of the leafs to root.\n     * @param node          Node on a path from tree leaf to root\n     * @param sibling       Sibling for a given node\n     * @param leafIndex     Index of the tree leaf\n     * @param nodeHeight    \"Level height\" for `node` (ZERO for leafs, ORIGIN_TREE_HEIGHT for root)\n     */\n    function getParent(bytes32 node, bytes32 sibling, uint256 leafIndex, uint256 nodeHeight)\n        internal\n        pure\n        returns (bytes32 parent)\n    {\n        // Index for `node` on its \"tree level\" is (leafIndex / 2**height)\n        // \"Left child\" has even index, \"right child\" has odd index\n        if ((leafIndex \u003e\u003e nodeHeight) \u0026 1 == 0) {\n            // Left child\n            return getParent(node, sibling);\n        } else {\n            // Right child\n            return getParent(sibling, node);\n        }\n    }\n\n    /// @notice Calculates the parent of tow nodes in the merkle tree.\n    /// @dev We use implementation with H(0,0) = 0\n    /// This makes EVERY empty node in the tree equal to ZERO,\n    /// saving us from storing H(0,0), H(H(0,0), H(0, 0)), and so on\n    /// @param leftChild    Left child of the calculated node\n    /// @param rightChild   Right child of the calculated node\n    /// @return parent      Value for the node having above mentioned children\n    function getParent(bytes32 leftChild, bytes32 rightChild) internal pure returns (bytes32 parent) {\n        if (leftChild == bytes32(0) \u0026\u0026 rightChild == bytes32(0)) {\n            return 0;\n        } else {\n            return keccak256(bytes.concat(leftChild, rightChild));\n        }\n    }\n\n    // ════════════════════════════════ ROOT/PROOF CALCULATION FOR A LIST OF LEAFS ═════════════════════════════════════\n\n    /**\n     * @notice Calculates merkle root for a list of given leafs.\n     * Merkle Tree is constructed by padding the list with ZERO values for leafs until list length is `2**height`.\n     * Merkle Root is calculated for the constructed tree, and then saved in `leafs[0]`.\n     * \u003e Note:\n     * \u003e - `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * \u003e - Caller is expected not to reuse `hashes` list after the call, and only use `leafs[0]` value,\n     * which is guaranteed to contain the calculated merkle root.\n     * \u003e - root is calculated using the `H(0,0) = 0` Merkle Tree implementation. See MerkleTree.sol for details.\n     * @dev Amount of leaves should be at most `2**height`\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param height    Height of the Merkle Tree to construct\n     */\n    function calculateRoot(bytes32[] memory hashes, uint256 height) internal pure {\n        uint256 levelLength = hashes.length;\n        // Amount of hashes could not exceed amount of leafs in tree with the given height\n        if (levelLength \u003e (1 \u003c\u003c height)) revert TreeHeightTooLow();\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\": the amount of iterations for the for loop above.\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n            }\n        }\n    }\n\n    /**\n     * @notice Generates a proof of inclusion of a leaf in the list. If the requested index is outside\n     * of the list range, generates a proof of inclusion for an empty leaf (proof of non-inclusion).\n     * The Merkle Tree is constructed by padding the list with ZERO values until list length is a power of two\n     * __AND__ index is in the extended list range. For example:\n     *  - `hashes.length == 6` and `0 \u003c= index \u003c= 7` will \"extend\" the list to 8 entries.\n     *  - `hashes.length == 6` and `7 \u003c index \u003c= 15` will \"extend\" the list to 16 entries.\n     * \u003e Note: `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * Caller is expected not to reuse `hashes` list after the call.\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param index     Leaf index to generate the proof for\n     * @return proof    Generated merkle proof\n     */\n    function calculateProof(bytes32[] memory hashes, uint256 index) internal pure returns (bytes32[] memory proof) {\n        // Use only meaningful values for the shortened proof\n        // Check if index is within the list range (we want to generates proofs for outside leafs as well)\n        uint256 height = getHeight(index \u003c hashes.length ? hashes.length : (index + 1));\n        proof = new bytes32[](height);\n        uint256 levelLength = hashes.length;\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Use sibling for the merkle proof; `index^1` is index of our sibling\n                proof[h] = (index ^ 1 \u003c levelLength) ? hashes[index ^ 1] : bytes32(0);\n\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\"\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n                // Traverse to parent node\n                index \u003e\u003e= 1;\n            }\n        }\n    }\n\n    /// @notice Returns the height of the tree having a given amount of leafs.\n    function getHeight(uint256 leafs) internal pure returns (uint256 height) {\n        uint256 amount = 1;\n        while (amount \u003c leafs) {\n            unchecked {\n                ++height;\n            }\n            amount \u003c\u003c= 1;\n        }\n    }\n}\n\n// contracts/libs/stack/GasData.sol\n\n/// GasData in encoded data with \"basic information about gas prices\" for some chain.\ntype GasData is uint96;\n\nusing GasDataLib for GasData global;\n\n/// ChainGas is encoded data with given chain's \"basic information about gas prices\".\ntype ChainGas is uint128;\n\nusing GasDataLib for ChainGas global;\n\n/// Library for encoding and decoding GasData and ChainGas structs.\n/// # GasData\n/// `GasData` is a struct to store the \"basic information about gas prices\", that could\n/// be later used to approximate the cost of a message execution, and thus derive the\n/// minimal tip values for sending a message to the chain.\n/// \u003e - `GasData` is supposed to be cached by `GasOracle` contract, allowing to store the\n/// \u003e approximates instead of the exact values, and thus save on storage costs.\n/// \u003e - For instance, if `GasOracle` only updates the values on +- 10% change, having an\n/// \u003e 0.4% error on the approximates would be acceptable.\n/// `GasData` is supposed to be included in the Origin's state, which are synced across\n/// chains using Agent-signed snapshots and attestations.\n/// ## GasData stack layout (from highest bits to lowest)\n///\n/// | Position   | Field        | Type   | Bytes | Description                                         |\n/// | ---------- | ------------ | ------ | ----- | --------------------------------------------------- |\n/// | (012..010] | gasPrice     | uint16 | 2     | Gas price for the chain (in Wei per gas unit)       |\n/// | (010..008] | dataPrice    | uint16 | 2     | Calldata price (in Wei per byte of content)         |\n/// | (008..006] | execBuffer   | uint16 | 2     | Tx fee safety buffer for message execution (in Wei) |\n/// | (006..004] | amortAttCost | uint16 | 2     | Amortized cost for attestation submission (in Wei)  |\n/// | (004..002] | etherPrice   | uint16 | 2     | Chain's Ether Price / Mainnet Ether Price (in BWAD) |\n/// | (002..000] | markup       | uint16 | 2     | Markup for the message execution (in BWAD)          |\n/// \u003e See Number.sol for more details on `Number` type and BWAD (binary WAD) math.\n///\n/// ## ChainGas stack layout (from highest bits to lowest)\n///\n/// | Position   | Field   | Type   | Bytes | Description      |\n/// | ---------- | ------- | ------ | ----- | ---------------- |\n/// | (016..004] | gasData | uint96 | 12    | Chain's gas data |\n/// | (004..000] | domain  | uint32 | 4     | Chain's domain   |\nlibrary GasDataLib {\n    /// @dev Amount of bits to shift to gasPrice field\n    uint96 private constant SHIFT_GAS_PRICE = 10 * 8;\n    /// @dev Amount of bits to shift to dataPrice field\n    uint96 private constant SHIFT_DATA_PRICE = 8 * 8;\n    /// @dev Amount of bits to shift to execBuffer field\n    uint96 private constant SHIFT_EXEC_BUFFER = 6 * 8;\n    /// @dev Amount of bits to shift to amortAttCost field\n    uint96 private constant SHIFT_AMORT_ATT_COST = 4 * 8;\n    /// @dev Amount of bits to shift to etherPrice field\n    uint96 private constant SHIFT_ETHER_PRICE = 2 * 8;\n\n    /// @dev Amount of bits to shift to gasData field\n    uint128 private constant SHIFT_GAS_DATA = 4 * 8;\n\n    // ═════════════════════════════════════════════════ GAS DATA ══════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded GasData struct with the given fields.\n    /// @param gasPrice_        Gas price for the chain (in Wei per gas unit)\n    /// @param dataPrice_       Calldata price (in Wei per byte of content)\n    /// @param execBuffer_      Tx fee safety buffer for message execution (in Wei)\n    /// @param amortAttCost_    Amortized cost for attestation submission (in Wei)\n    /// @param etherPrice_      Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n    /// @param markup_          Markup for the message execution (in BWAD)\n    function encodeGasData(\n        Number gasPrice_,\n        Number dataPrice_,\n        Number execBuffer_,\n        Number amortAttCost_,\n        Number etherPrice_,\n        Number markup_\n    ) internal pure returns (GasData) {\n        // Number type wraps uint16, so could safely be casted to uint96\n        // forgefmt: disable-next-item\n        return GasData.wrap(\n            uint96(Number.unwrap(gasPrice_)) \u003c\u003c SHIFT_GAS_PRICE |\n            uint96(Number.unwrap(dataPrice_)) \u003c\u003c SHIFT_DATA_PRICE |\n            uint96(Number.unwrap(execBuffer_)) \u003c\u003c SHIFT_EXEC_BUFFER |\n            uint96(Number.unwrap(amortAttCost_)) \u003c\u003c SHIFT_AMORT_ATT_COST |\n            uint96(Number.unwrap(etherPrice_)) \u003c\u003c SHIFT_ETHER_PRICE |\n            uint96(Number.unwrap(markup_))\n        );\n    }\n\n    /// @notice Wraps padded uint256 value into GasData struct.\n    function wrapGasData(uint256 paddedGasData) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(paddedGasData));\n    }\n\n    /// @notice Returns the gas price, in Wei per gas unit.\n    function gasPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_GAS_PRICE));\n    }\n\n    /// @notice Returns the calldata price, in Wei per byte of content.\n    function dataPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_DATA_PRICE));\n    }\n\n    /// @notice Returns the tx fee safety buffer for message execution, in Wei.\n    function execBuffer(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_EXEC_BUFFER));\n    }\n\n    /// @notice Returns the amortized cost for attestation submission, in Wei.\n    function amortAttCost(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_AMORT_ATT_COST));\n    }\n\n    /// @notice Returns the ratio of Chain's Ether Price / Mainnet Ether Price, in BWAD math.\n    function etherPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_ETHER_PRICE));\n    }\n\n    /// @notice Returns the markup for the message execution, in BWAD math.\n    function markup(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data)));\n    }\n\n    // ════════════════════════════════════════════════ CHAIN DATA ═════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded ChainGas struct with the given fields.\n    /// @param gasData_ Chain's gas data\n    /// @param domain_  Chain's domain\n    function encodeChainGas(GasData gasData_, uint32 domain_) internal pure returns (ChainGas) {\n        // GasData type wraps uint96, so could safely be casted to uint128\n        return ChainGas.wrap(uint128(GasData.unwrap(gasData_)) \u003c\u003c SHIFT_GAS_DATA | uint128(domain_));\n    }\n\n    /// @notice Wraps padded uint256 value into ChainGas struct.\n    function wrapChainGas(uint256 paddedChainGas) internal pure returns (ChainGas) {\n        // Casting to uint128 will truncate the highest bits, which is the behavior we want\n        return ChainGas.wrap(uint128(paddedChainGas));\n    }\n\n    /// @notice Returns the chain's gas data.\n    function gasData(ChainGas data) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(ChainGas.unwrap(data) \u003e\u003e SHIFT_GAS_DATA));\n    }\n\n    /// @notice Returns the chain's domain.\n    function domain(ChainGas data) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(ChainGas.unwrap(data));\n    }\n\n    /// @notice Returns the hash for the list of ChainGas structs.\n    function snapGasHash(ChainGas[] memory snapGas) internal pure returns (bytes32 snapGasHash_) {\n        // Use assembly to calculate the hash of the array without copying it\n        // ChainGas takes a single word of storage, thus ChainGas[] is stored in the following way:\n        // 0x00: length of the array, in words\n        // 0x20: first ChainGas struct\n        // 0x40: second ChainGas struct\n        // And so on...\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Find the location where the array data starts, we add 0x20 to skip the length field\n            let loc := add(snapGas, 0x20)\n            // Load the length of the array (in words).\n            // Shifting left 5 bits is equivalent to multiplying by 32: this converts from words to bytes.\n            let len := shl(5, mload(snapGas))\n            // Calculate the hash of the array\n            snapGasHash_ := keccak256(loc, len)\n        }\n    }\n}\n\n// contracts/libs/stack/Header.sol\n\n/// Header is encoded data with \"general routing information\".\ntype Header is uint136;\n\nusing HeaderLib for Header global;\n\n/// Types of messages supported by Origin-Destination\n/// - Base: message sent by protocol user, contains tips\n/// - Manager: message sent between AgentManager contracts located on different chains, no tips\nenum MessageFlag {\n    Base,\n    Manager\n}\n\nusing HeaderLib for MessageFlag global;\n\n/// Library for formatting _the header part_ of _the messages used by Origin and Destination_.\n/// - Header represents general information for routing a Message for Origin and Destination.\n/// - Header occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n///\n/// # Header stack layout (from highest bits to lowest)\n///\n/// | Position   | Field            | Type   | Bytes | Description                             |\n/// | ---------- | ---------------- | ------ | ----- | --------------------------------------- |\n/// | (017..016] | flag             | uint8  | 1     | Flag specifying the type of message     |\n/// | (016..012] | origin           | uint32 | 4     | Domain where message originated         |\n/// | (012..008] | nonce            | uint32 | 4     | Message nonce on the origin domain      |\n/// | (008..004] | destination      | uint32 | 4     | Domain where message will be executed   |\n/// | (004..000] | optimisticPeriod | uint32 | 4     | Optimistic period that will be enforced |\nlibrary HeaderLib {\n    /// @dev Amount of bits to shift to flag field\n    uint136 private constant SHIFT_FLAG = 16 * 8;\n    /// @dev Amount of bits to shift to origin field\n    uint136 private constant SHIFT_ORIGIN = 12 * 8;\n    /// @dev Amount of bits to shift to nonce field\n    uint136 private constant SHIFT_NONCE = 8 * 8;\n    /// @dev Amount of bits to shift to destination field\n    uint136 private constant SHIFT_DESTINATION = 4 * 8;\n\n    /// @notice Returns an encoded header with provided fields\n    /// @param origin_              Domain of origin chain\n    /// @param nonce_               Message nonce on origin chain\n    /// @param destination_         Domain of destination chain\n    /// @param optimisticPeriod_    Optimistic period for message execution\n    function encodeHeader(\n        MessageFlag flag_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint32 destination_,\n        uint32 optimisticPeriod_\n    ) internal pure returns (Header) {\n        // All casts below are upcasts, so they are safe\n        // forgefmt: disable-next-item\n        return Header.wrap(\n            uint136(uint8(flag_)) \u003c\u003c SHIFT_FLAG |\n            uint136(origin_) \u003c\u003c SHIFT_ORIGIN |\n            uint136(nonce_) \u003c\u003c SHIFT_NONCE |\n            uint136(destination_) \u003c\u003c SHIFT_DESTINATION |\n            uint136(optimisticPeriod_)\n        );\n    }\n\n    /// @notice Checks that the header is a valid encoded header.\n    function isHeader(uint256 paddedHeader) internal pure returns (bool) {\n        // Check that flag is within range\n        return _flag(paddedHeader) \u003c= uint8(type(MessageFlag).max);\n    }\n\n    /// @notice Wraps the padded encoded request into a Header-typed value.\n    /// @dev The \"padded\" header is simply an encoded header casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded headers\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedHeader) internal pure returns (Header) {\n        // Check that flag is within range\n        if (!isHeader(paddedHeader)) revert FlagOutOfRange();\n        // Casting to uint136 will truncate the highest bits, which is the behavior we want\n        return Header.wrap(uint136(paddedHeader));\n    }\n\n    /// @notice Returns header's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Header header) internal pure returns (bytes32 hashedHeader) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store header in scratch space\n            mstore(0, header)\n            // Compute hash of header padded to 32 bytes\n            hashedHeader := keccak256(0, 32)\n        }\n    }\n\n    // ══════════════════════════════════════════════ HEADER SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns header's flag field\n    function flag(Header header) internal pure returns (MessageFlag) {\n        // We check that flag is within range when wrapping the header, so this cast is safe\n        return MessageFlag(_flag(Header.unwrap(header)));\n    }\n\n    /// @notice Returns header's origin field\n    function origin(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_ORIGIN);\n    }\n\n    /// @notice Returns header's nonce field\n    function nonce(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_NONCE);\n    }\n\n    /// @notice Returns header's destination field\n    function destination(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_DESTINATION);\n    }\n\n    /// @notice Returns header's optimistic seconds field\n    function optimisticPeriod(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns header's flag field without casting to MessageFlag\n    function _flag(uint256 paddedHeader) private pure returns (uint8) {\n        // Casting to uint8 will truncate the highest bits, which is the behavior we want\n        return uint8(paddedHeader \u003e\u003e SHIFT_FLAG);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n     * constructor.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall \u0026\u0026 _initialized \u003c 1) || (!AddressUpgradeable.isContract(address(this)) \u0026\u0026 _initialized == 1),\n            \"Initializable: contract is already initialized\"\n        );\n        _initialized = 1;\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: setting the version to 255 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing \u0026\u0026 _initialized \u003c version, \"Initializable: contract is already initialized\");\n        _initialized = version;\n        _initializing = true;\n        _;\n        _initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        require(_initializing, \"Initializable: contract is not initializing\");\n        _;\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized != type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint8) {\n        return _initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _initializing;\n    }\n}\n\n// contracts/interfaces/IAgentManager.sol\n\ninterface IAgentManager {\n    /**\n     * @notice Allows Inbox to open a Dispute between a Guard and a Notary, if they are both not in Dispute already.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Guard or Notary is already in Dispute.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Allows Inbox to slash an agent, if their fraud was proven.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Domain doesn't match the saved agent domain.\n     * @param domain    Domain where the Agent is active\n     * @param agent     Address of the Agent\n     * @param prover    Address that initially provided fraud proof\n     */\n    function slashAgent(uint32 domain, address agent, address prover) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest known root of the Agent Merkle Tree.\n     */\n    function agentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns the number of opened Disputes.\n     * @dev This includes the Disputes that have been resolved already.\n     */\n    function getDisputesAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns information about the dispute with the given index.\n     * @dev Will revert if dispute with given index hasn't been opened yet.\n     * @param index             Dispute index\n     * @return guard            Address of the Guard in the Dispute\n     * @return notary           Address of the Notary in the Dispute\n     * @return slashedAgent     Address of the Agent who was slashed when Dispute was resolved\n     * @return fraudProver      Address who provided fraud proof to resolve the Dispute\n     * @return reportPayload    Raw payload with report data that led to the Dispute\n     * @return reportSignature  Guard signature for the report payload\n     */\n    function getDispute(uint256 index)\n        external\n        view\n        returns (\n            address guard,\n            address notary,\n            address slashedAgent,\n            address fraudProver,\n            bytes memory reportPayload,\n            bytes memory reportSignature\n        );\n\n    /**\n     * @notice Returns the current Dispute status of a given agent. See Structures.sol for details.\n     * @dev Every returned value will be set to zero if agent was not slashed and is not in Dispute.\n     * `rival` and `disputePtr` will be set to zero if the agent was slashed without being in Dispute.\n     * @param agent         Agent address\n     * @return flag         Flag describing the current Dispute status for the agent: None/Pending/Slashed\n     * @return rival        Address of the rival agent in the Dispute\n     * @return fraudProver  Address who provided fraud proof to resolve the Dispute\n     * @return disputePtr   Index of the opened Dispute PLUS ONE. Zero if agent is not in Dispute.\n     */\n    function disputeStatus(address agent)\n        external\n        view\n        returns (DisputeFlag flag, address rival, address fraudProver, uint256 disputePtr);\n}\n\n// contracts/interfaces/IAgentSecured.sol\n\ninterface IAgentSecured {\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * between a Guard and a Notary has been opened.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * has been resolved due to one of the agents being slashed.\n     * \u003e `rivalIndex` will be ZERO, if the slashed agent was not in the Dispute.\n     * @param slashedIndex  Index of the slashed agent in the Agent Merkle Tree\n     * @param rivalIndex    Index of the their Dispute Rival in the Agent Merkle Tree\n     */\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the address of the local AgentManager contract, which is treated as\n     * the \"source of truth\" for agent statuses.\n     */\n    function agentManager() external view returns (address);\n\n    /**\n     * @notice Returns the address of the local Inbox contract, which is treated as\n     * the \"source of truth\" for agent-signed statements.\n     * @dev Inbox passes verified agent statements to `IAgentSecured` contract.\n     */\n    function inbox() external view returns (address);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns (flag, openedAt, resolvedAt) that describes the latest status of\n     * the latest dispute for an agent with a given index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param agentIndex    Agent index in the Agent Merkle Tree\n     * @return              Latest dispute status for the given agent: (flag, openedAt, resolvedAt)\n     */\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory);\n}\n\n// contracts/libs/memory/ByteString.sol\n\n/// @dev CallData is a memory view over the payload to be used for an external call, i.e.\n/// recipient.call(callData). Its length is always (4 + 32 * N) bytes:\n/// - First 4 bytes represent the function selector.\n/// - 32 * N bytes represent N words that function arguments occupy.\ntype CallData is uint256;\n\n/// @dev Attach library functions to CallData\nusing ByteString for CallData global;\n\n/// @dev Signature is a memory view over a \"65 bytes\" array representing a ECDSA signature.\ntype Signature is uint256;\n\n/// @dev Attach library functions to Signature\nusing ByteString for Signature global;\n\nlibrary ByteString {\n    using MemViewLib for bytes;\n\n    /**\n     * @dev non-compact ECDSA signatures are enforced as of OZ 4.7.3\n     *\n     *      Signature payload memory layout\n     * [000 .. 032) r   bytes32 32 bytes\n     * [032 .. 064) s   bytes32 32 bytes\n     * [064 .. 065) v   uint8    1 byte\n     */\n    uint256 internal constant SIGNATURE_LENGTH = 65;\n    uint256 private constant OFFSET_R = 0;\n    uint256 private constant OFFSET_S = 32;\n    uint256 private constant OFFSET_V = 64;\n\n    /**\n     * @dev Calldata memory layout\n     * [000 .. 004) selector    bytes4  4 bytes\n     *      Optional: N function arguments\n     * [004 .. 036) arg1        bytes32 32 bytes\n     *      ..\n     * [AAA .. END) argN        bytes32 32 bytes\n     */\n    uint256 internal constant SELECTOR_LENGTH = 4;\n    uint256 private constant OFFSET_SELECTOR = 0;\n    uint256 private constant OFFSET_ARGUMENTS = SELECTOR_LENGTH;\n\n    // ═════════════════════════════════════════════════ SIGNATURE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the signature payload from the given values.\n     * @dev Using ByteString.formatSignature({r: r, s: s, v: v}) will make sure\n     * that params are given in the right order.\n     */\n    function formatSignature(bytes32 r, bytes32 s, uint8 v) internal pure returns (bytes memory) {\n        return abi.encodePacked(r, s, v);\n    }\n\n    /**\n     * @notice Returns a Signature view over for the given payload.\n     * @dev Will revert if the payload is not a signature.\n     */\n    function castToSignature(bytes memory payload) internal pure returns (Signature) {\n        return castToSignature(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Signature view.\n     * @dev Will revert if the memory view is not over a signature.\n     */\n    function castToSignature(MemView memView) internal pure returns (Signature) {\n        if (!isSignature(memView)) revert UnformattedSignature();\n        return Signature.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a signature\n     */\n    function isSignature(MemView memView) internal pure returns (bool) {\n        return memView.len() == SIGNATURE_LENGTH;\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Signature signature) internal pure returns (MemView) {\n        return MemView.wrap(Signature.unwrap(signature));\n    }\n\n    // ═════════════════════════════════════════════ SIGNATURE SLICING ═════════════════════════════════════════════════\n\n    /// @notice Unpacks signature payload into (r, s, v) parameters.\n    /// @dev Make sure to verify signature length with isSignature() beforehand.\n    function toRSV(Signature signature) internal pure returns (bytes32 r, bytes32 s, uint8 v) {\n        // Get the underlying memory view\n        MemView memView = unwrap(signature);\n        r = memView.index({index_: OFFSET_R, bytes_: 32});\n        s = memView.index({index_: OFFSET_S, bytes_: 32});\n        // Can be safely casted to uint8, since we index a single byte\n        v = uint8(memView.indexUint({index_: OFFSET_V, bytes_: 1}));\n    }\n\n    // ═════════════════════════════════════════════════ CALLDATA ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the calldata with the modified arguments:\n     * the existing arguments are prepended with the arguments from the prefix.\n     * @dev Given:\n     *  - `calldata = abi.encodeWithSelector(foo.selector, d, e);`\n     *  - `prefix = abi.encode(a, b, c);`\n     *  - `a`, `b`, `c` are arguments of static type (i.e. not dynamically sized ones)\n     *      Then:\n     *  - Function will return abi.encodeWithSelector(foo.selector, a, c, c, d, e)\n     *  - Returned calldata will trigger `foo(a, b, c, d, e)` when used for a contract call.\n     * Note: for clarification as to what types are considered static, see\n     * https://docs.soliditylang.org/en/latest/abi-spec.html#formal-specification-of-the-encoding\n     * @param callData  Calldata that needs to be modified\n     * @param prefix    ABI-encoded arguments to use as the first arguments in the new calldata\n     * @return Modified calldata having prefix as the first arguments.\n     */\n    function addPrefix(CallData callData, bytes memory prefix) internal view returns (bytes memory) {\n        // Prefix should occupy a whole amount of words in memory\n        if (!_fullWords(prefix.length)) revert UnformattedCallDataPrefix();\n        MemView[] memory views = new MemView[](3);\n        // Use payload's function selector\n        views[0] = abi.encodePacked(callData.callSelector()).ref();\n        // Use prefix as the first arguments\n        views[1] = prefix.ref();\n        // Use payload's remaining arguments\n        views[2] = callData.arguments();\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a CallData view over for the given payload.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(bytes memory payload) internal pure returns (CallData) {\n        return castToCallData(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a CallData view.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(MemView memView) internal pure returns (CallData) {\n        if (!isCallData(memView)) revert UnformattedCallData();\n        return CallData.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a valid calldata, i.e.\n     * a function selector, followed by arbitrary amount of arguments.\n     */\n    function isCallData(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Calldata should at least have a function selector\n        if (length \u003c SELECTOR_LENGTH) return false;\n        // The remainder of the calldata should be exactly N memory words (N \u003e= 0)\n        return _fullWords(length - SELECTOR_LENGTH);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(CallData callData) internal pure returns (MemView) {\n        return MemView.wrap(CallData.unwrap(callData));\n    }\n\n    /// @notice Returns callData's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(CallData callData) internal pure returns (bytes32) {\n        return callData.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ CALLDATA SLICING ══════════════════════════════════════════════════\n\n    /**\n     * @notice Returns amount of memory words (32 byte chunks) the function arguments\n     * occupy in the calldata.\n     * @dev This might differ from amount of arguments supplied, if any of the arguments\n     * occupies more than one memory slot. It is true, however, that argument part of the payload\n     * occupies exactly N words, even for dynamic types like `bytes`\n     */\n    function argumentWords(CallData callData) internal pure returns (uint256) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        // Equivalent of (length - SELECTOR_LENGTH) / 32\n        return (memView.len() - SELECTOR_LENGTH) \u003e\u003e 5;\n    }\n\n    /// @notice Returns selector for the provided calldata.\n    function callSelector(CallData callData) internal pure returns (bytes4) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return bytes4(memView.index({index_: OFFSET_SELECTOR, bytes_: SELECTOR_LENGTH}));\n    }\n\n    /// @notice Returns abi encoded arguments for the provided calldata.\n    function arguments(CallData callData) internal pure returns (MemView) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return memView.sliceFrom({index_: OFFSET_ARGUMENTS});\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if length is full amount of memory words (32 bytes).\n    function _fullWords(uint256 length) internal pure returns (bool) {\n        // The equivalent of length % 32 == 0\n        return length \u0026 31 == 0;\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n    function __Context_init() internal onlyInitializing {\n    }\n\n    function __Context_init_unchained() internal onlyInitializing {\n    }\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[50] private __gap;\n}\n\n// contracts/libs/merkle/MerkleTree.sol\n\n/// `BaseTree` is a struct representing incremental merkle tree.\n/// - Contains only the current branch.\n/// - The number of inserted leaves is stored externally, and is later supplied for tree operations.\n/// - Has a fixed height of `ORIGIN_TREE_HEIGHT`.\n/// - Can store up to `2 ** ORIGIN_TREE_HEIGHT - 1` leaves.\n/// \u003e Note: the hash function for the tree `H(x, y)` is defined as:\n/// \u003e - `H(0,0) = 0`\n/// \u003e - `H(x,y) = keccak256(x, y), when (x != 0 || y != 0)`\n/// ## Invariant for leafs\n/// - The leftmost empty leaf has `index == count`, where `count` is the amount of the inserted leafs so far.\n/// - Value for any empty leaf or node is bytes32(0).\n/// ## Invariant for current branch\n/// `branch[i]` is always the value of a node on the i-th level.\n/// Levels are numbered from leafs to root: `0 .. ORIGIN_TREE_HEIGHT`.\n/// `branch[i]` stores the value for the node, such that:\n//  - The node is a \"left child\" (e.g. has an even index).\n/// - The node must have two non-empty children.\n/// - Out of all level's \"left child\" nodes with \"non-empty children\",\n/// the one with the biggest index (the rightmost one) is stored as `branch[i]`.\n/// \u003e __`branch` could be used to form a proof of inclusion for the first empty leaf (`index == count`).__\n/// _Here is how:_\n/// - Let's walk along the path from the \"first empty leaf\" to the root.\n/// - i-th bit of the \"first empty leaf\" index (which is equal to `count`) determines if the path's node\n/// for this i-th level is a \"left child\" or a \"right child\".\n/// - i-th bit in `count` is 0 → we are the left child on this level → sibling is the right child\n/// that does not exist yet → `proof[i] = bytes32(0)`.\n/// - i-th bit in `count` is 1 → we are the right child on this level → sibling is the left child\n/// sibling is the rightmost \"left child\" node on the level → `proof[i] = branch[i]`.\n/// \u003e Therefore `proof[i] = (count \u0026 (1 \u003c\u003c i)) == 0 ? bytes32(0) : branch[i])`\nstruct BaseTree {\n    bytes32[ORIGIN_TREE_HEIGHT] branch;\n}\n\nusing MerkleTree for BaseTree global;\n\n/// `HistoricalTree` is an incremental merkle tree keeping track of its historical merkle roots.\n/// \u003e - `roots[N]` is the root of the tree after `N` leafs were inserted\n/// \u003e - `roots[0] == bytes32(0)`\n/// @param tree     Incremental merkle tree\n/// @param roots    Historical merkle roots of the tree\nstruct HistoricalTree {\n    BaseTree tree;\n    bytes32[] roots;\n}\n\nusing MerkleTree for HistoricalTree global;\n\n/// `DynamicTree` is a struct representing a Merkle Tree with `2**AGENT_TREE_HEIGHT` leaves.\n/// - A single operation is available: update value for leaf with an arbitrary index (which might be a non-empty leaf).\n/// - This is done by requesting the proof of inclusion for the old value, which is used to both\n/// verify the old value, and calculate the new root.\n/// \u003e Based on Original idea from [ER forum post](https://ethresear.ch/t/efficient-on-chain-dynamic-merkle-tree/11054).\nstruct DynamicTree {\n    bytes32 root;\n}\n\nusing MerkleTree for DynamicTree global;\n\n/// MerkleTree is work based on Nomad's Merkle.sol, which is used under MIT OR Apache-2.0\n/// [link](https://github.com/nomad-xyz/monorepo/blob/main/packages/contracts-core/contracts/libs/Merkle.sol).\n/// With the following changes:\n/// - Adapted for Solidity 0.8.x.\n/// - Amount of tree leaves stored externally.\n/// - Added thorough documentation.\n/// - `H(0,0) = 0` optimization from [ER forum post](https://ethresear.ch/t/optimizing-sparse-merkle-trees/3751/6).\n/// \u003e Nomad's Merkle.sol is work based on eth2 deposit contract, which is used under CC0-1.0\n///[link](https://github.com/ethereum/deposit_contract/blob/dev/deposit_contract/contracts/validator_registration.v.py).\n/// With the following changes:\n/// \u003e - Implemented in Solidity 0.7.6 (eth2 deposit contract implemented in Vyper).\n/// \u003e - `H() = keccak256()` is used as the hashing function instead of `sha256()`.\nlibrary MerkleTree {\n    /// @dev For root calculation we need at least one empty leaf, thus the minus one in the formula.\n    uint256 internal constant MAX_LEAVES = 2 ** ORIGIN_TREE_HEIGHT - 1;\n\n    // ═════════════════════════════════════════════════ BASE TREE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Inserts `node` into merkle tree\n     * @dev Reverts if tree is full\n     * @param newCount  Amount of inserted leaves in the tree after the insertion (i.e. current + 1)\n     * @param node      Element to insert into tree\n     */\n    function insertBase(BaseTree storage tree, uint256 newCount, bytes32 node) internal {\n        if (newCount \u003e MAX_LEAVES) revert MerkleTreeFull();\n        // We go up the tree following the branch from the empty leaf AFTER the just inserted one.\n        // We stop when we find the first \"right child\" node.\n        // Its sibling is now the rightmost \"left child\" node that has two non-empty children.\n        // Therefore we need to update `tree.branch` value on this level.\n        // One could see that `tree.branch` value on lower and higher levels remain unchanged.\n\n        // Loop invariant: `node` is the current level's value for the branch from JUST INSERTED leaf\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            if ((newCount \u0026 1) == 1) {\n                // Found the first \"right child\" node on the branch from EMPTY leaf\n                // `node` is the value for node on branch from JUST INSERTED leaf\n                // Which in this case is the \"left child\".\n                // We update tree.branch and exit\n                tree.branch[i] = node;\n                return;\n            }\n            // On the branch from EMPTY leaf this is still a \"left child\".\n            // Meaning on branch from JUST INSERTED leaf, `node` is a right child.\n            // We compute value for `node` parent using `tree.branch` invariant:\n            // This is the rightmost \"left child\" node, which would be sibling of `node`.\n            node = MerkleMath.getParent(tree.branch[i], node);\n            // Get the parent index, and go to the next tree level\n            newCount \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n        // As the loop should always end prematurely with the `return` statement,\n        // this code should be unreachable. We assert `false` just to be safe.\n        assert(false);\n    }\n\n    /**\n     * @notice Calculates and returns current root of the merkle tree.\n     * @param count     Current amount of inserted leaves in the tree\n     * @return current  Calculated root of `tree`\n     */\n    function rootBase(BaseTree storage tree, uint256 count) internal view returns (bytes32 current) {\n        // To calculate the root we follow the branch of first EMPTY leaf (index == count)\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            // Check if we are the left or the right child on the current level\n            if ((count \u0026 1) == 1) {\n                // We are the right child. Our sibling is the \"rightmost\" \"left-child\" node\n                // that has two non-empty children → sibling is `tree.branch[i]`\n                current = MerkleMath.getParent(tree.branch[i], current);\n            } else {\n                // We are the left child. Our sibling does not exist yet → sibling is EMPTY\n                current = MerkleMath.getParent(current, bytes32(0));\n            }\n            // Get the parent index, and go to the next tree level\n            count \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    // ══════════════════════════════════════════════ HISTORICAL TREE ══════════════════════════════════════════════════\n\n    /// @notice Initializes the historical roots for the tree by inserting an empty root.\n    // solhint-disable-next-line ordering\n    function initializeRoots(HistoricalTree storage tree) internal returns (bytes32 savedRoot) {\n        // This should only be called once, when the contract is initialized\n        assert(tree.roots.length == 0);\n        // Save root for empty merkle tree: bytes32(0)\n        tree.roots.push(savedRoot);\n    }\n\n    /// @notice Inserts a new leaf into the merkle tree.\n    /// @dev Reverts if tree is full.\n    /// @param node         Element to insert into tree\n    /// @return newRoot     Merkle root after the leaf was inserted\n    function insert(HistoricalTree storage tree, bytes32 node) internal returns (bytes32 newRoot) {\n        // Tree count after the new leaf will be inserted (we store roots[0] as root of empty tree)\n        uint256 newCount = tree.roots.length;\n        tree.tree.insertBase(newCount, node);\n        // Save the new root\n        newRoot = tree.tree.rootBase(newCount);\n        tree.roots.push(newRoot);\n    }\n\n    /// @notice Returns the historical root of the merkle tree.\n    /// @dev Reverts if not enough leafs have been inserted.\n    /// @param count            Amount of leafs in the tree at some point of time\n    /// @return historicalRoot  Merkle root after `count` leafs were inserted\n    function root(HistoricalTree storage tree, uint256 count) internal view returns (bytes32 historicalRoot) {\n        if (count \u003e= tree.roots.length) revert NotEnoughLeafs();\n        return tree.roots[count];\n    }\n\n    // ═══════════════════════════════════════════════ DYNAMIC TREE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Updates the value for the leaf with the given index in the Dynamic Merkle Tree.\n     * @dev Will revert if incorrect proof of inclusion for old value is supplied.\n     * @param tree          Dynamic merkle tree\n     * @param index         Index of the leaf to update\n     * @param oldValue      Previous value of the leaf\n     * @param branch        Proof of inclusion of previous value into the tree\n     * @param newValue      New leaf value to assign\n     * @return newRoot      New value for the Merkle Root after the leaf is updated\n     */\n    function update(\n        DynamicTree storage tree,\n        uint256 index,\n        bytes32 oldValue,\n        bytes32[] memory branch,\n        bytes32 newValue\n    ) internal returns (bytes32 newRoot) {\n        // Check that the old value + proof result in a correct root\n        if (MerkleMath.proofRoot(index, oldValue, branch, AGENT_TREE_HEIGHT) != tree.root) {\n            revert LeafNotProven();\n        }\n        // New root is new value + the same proof (values for sibling nodes are not updated)\n        newRoot = MerkleMath.proofRoot(index, newValue, branch, AGENT_TREE_HEIGHT);\n        // Write the new root\n        tree.root = newRoot;\n    }\n}\n\n// contracts/libs/stack/Tips.sol\n\n/// Tips is encoded data with \"tips paid for sending a base message\".\n/// Note: even though uint256 is also an underlying type for MemView, Tips is stored ON STACK.\ntype Tips is uint256;\n\nusing TipsLib for Tips global;\n\n/// # Tips\n/// Library for formatting _the tips part_ of _the base messages_.\n///\n/// ## How the tips are awarded\n/// Tips are paid for sending a base message, and are split across all the agents that\n/// made the message execution on destination chain possible.\n/// ### Summit tips\n/// Split between:\n///     - Guard posting a snapshot with state ST_G for the origin chain.\n///     - Notary posting a snapshot SN_N using ST_G. This creates attestation A.\n///     - Notary posting a message receipt after it is executed on destination chain.\n/// ### Attestation tips\n/// Paid to:\n///     - Notary posting attestation A to destination chain.\n/// ### Execution tips\n/// Paid to:\n///     - First executor performing a valid execution attempt (correct proofs, optimistic period over),\n///      using attestation A to prove message inclusion on origin chain, whether the recipient reverted or not.\n/// ### Delivery tips.\n/// Paid to:\n///     - Executor who successfully executed the message on destination chain.\n///\n/// ## Tips encoding\n/// - Tips occupy a single storage word, and thus are stored on stack instead of being stored in memory.\n/// - The actual tip values should be determined by multiplying stored values by divided by TIPS_MULTIPLIER=2**32.\n/// - Tips are packed into a single word of storage, while allowing real values up to ~8*10**28 for every tip category.\n/// \u003e The only downside is that the \"real tip values\" are now multiplies of ~4*10**9, which should be fine even for\n/// the chains with the most expensive gas currency.\n/// # Tips stack layout (from highest bits to lowest)\n///\n/// | Position   | Field          | Type   | Bytes | Description                                                |\n/// | ---------- | -------------- | ------ | ----- | ---------------------------------------------------------- |\n/// | (032..024] | summitTip      | uint64 | 8     | Tip for agents interacting with Summit contract            |\n/// | (024..016] | attestationTip | uint64 | 8     | Tip for Notary posting attestation to Destination contract |\n/// | (016..008] | executionTip   | uint64 | 8     | Tip for valid execution attempt on destination chain       |\n/// | (008..000] | deliveryTip    | uint64 | 8     | Tip for successful message delivery on destination chain   |\n\nlibrary TipsLib {\n    using SafeCast for uint256;\n\n    /// @dev Amount of bits to shift to summitTip field\n    uint256 private constant SHIFT_SUMMIT_TIP = 24 * 8;\n    /// @dev Amount of bits to shift to attestationTip field\n    uint256 private constant SHIFT_ATTESTATION_TIP = 16 * 8;\n    /// @dev Amount of bits to shift to executionTip field\n    uint256 private constant SHIFT_EXECUTION_TIP = 8 * 8;\n\n    // ═══════════════════════════════════════════════════ TIPS ════════════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips with the given fields\n    /// @param summitTip_        Tip for agents interacting with Summit contract, divided by TIPS_MULTIPLIER\n    /// @param attestationTip_   Tip for Notary posting attestation to Destination contract, divided by TIPS_MULTIPLIER\n    /// @param executionTip_     Tip for valid execution attempt on destination chain, divided by TIPS_MULTIPLIER\n    /// @param deliveryTip_      Tip for successful message delivery on destination chain, divided by TIPS_MULTIPLIER\n    function encodeTips(uint64 summitTip_, uint64 attestationTip_, uint64 executionTip_, uint64 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // forgefmt: disable-next-item\n        return Tips.wrap(\n            uint256(summitTip_) \u003c\u003c SHIFT_SUMMIT_TIP |\n            uint256(attestationTip_) \u003c\u003c SHIFT_ATTESTATION_TIP |\n            uint256(executionTip_) \u003c\u003c SHIFT_EXECUTION_TIP |\n            uint256(deliveryTip_)\n        );\n    }\n\n    /// @notice Convenience function to encode tips with uint256 values.\n    function encodeTips256(uint256 summitTip_, uint256 attestationTip_, uint256 executionTip_, uint256 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // In practice, the tips amounts are not supposed to be higher than 2**96, and with 32 bits of granularity\n        // using uint64 is enough to store the values. However, we still check for overflow just in case.\n        // TODO: consider using Number type to store the tips values.\n        return encodeTips({\n            summitTip_: (summitTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            attestationTip_: (attestationTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            executionTip_: (executionTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            deliveryTip_: (deliveryTip_ \u003e\u003e TIPS_GRANULARITY).toUint64()\n        });\n    }\n\n    /// @notice Wraps the padded encoded tips into a Tips-typed value.\n    /// @dev There is no actual padding here, as the underlying type is already uint256,\n    /// but we include this function for consistency and to be future-proof, if tips will eventually use anything\n    /// smaller than uint256.\n    function wrapPadded(uint256 paddedTips) internal pure returns (Tips) {\n        return Tips.wrap(paddedTips);\n    }\n\n    /**\n     * @notice Returns a formatted Tips payload specifying empty tips.\n     * @return Formatted tips\n     */\n    function emptyTips() internal pure returns (Tips) {\n        return Tips.wrap(0);\n    }\n\n    /// @notice Returns tips's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Tips tips) internal pure returns (bytes32 hashedTips) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store tips in scratch space\n            mstore(0, tips)\n            // Compute hash of tips padded to 32 bytes\n            hashedTips := keccak256(0, 32)\n        }\n    }\n\n    // ═══════════════════════════════════════════════ TIPS SLICING ════════════════════════════════════════════════════\n\n    /// @notice Returns summitTip field\n    function summitTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_SUMMIT_TIP);\n    }\n\n    /// @notice Returns attestationTip field\n    function attestationTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_ATTESTATION_TIP);\n    }\n\n    /// @notice Returns executionTip field\n    function executionTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_EXECUTION_TIP);\n    }\n\n    /// @notice Returns deliveryTip field\n    function deliveryTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips));\n    }\n\n    // ════════════════════════════════════════════════ TIPS VALUE ═════════════════════════════════════════════════════\n\n    /// @notice Returns total value of the tips payload.\n    /// This is the sum of the encoded values, scaled up by TIPS_MULTIPLIER\n    function value(Tips tips) internal pure returns (uint256 value_) {\n        value_ = uint256(tips.summitTip()) + tips.attestationTip() + tips.executionTip() + tips.deliveryTip();\n        value_ \u003c\u003c= TIPS_GRANULARITY;\n    }\n\n    /// @notice Increases the delivery tip to match the new value.\n    function matchValue(Tips tips, uint256 newValue) internal pure returns (Tips newTips) {\n        uint256 oldValue = tips.value();\n        if (newValue \u003c oldValue) revert TipsValueTooLow();\n        // We want to increase the delivery tip, while keeping the other tips the same\n        unchecked {\n            uint256 delta = (newValue - oldValue) \u003e\u003e TIPS_GRANULARITY;\n            // `delta` fits into uint224, as TIPS_GRANULARITY is 32, so this never overflows uint256.\n            // In practice, this will never overflow uint64 as well, but we still check it just in case.\n            if (delta + tips.deliveryTip() \u003e type(uint64).max) revert TipsOverflow();\n            // Delivery tips occupy lowest 8 bytes, so we can just add delta to the tips value\n            // to effectively increase the delivery tip (knowing that delta fits into uint64).\n            newTips = Tips.wrap(Tips.unwrap(tips) + delta);\n        }\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    function __Ownable_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable_init_unchained() internal onlyInitializing {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n    function __Ownable2Step_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable2Step_init_unchained() internal onlyInitializing {\n    }\n    address private _pendingOwner;\n\n    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Returns the address of the pending owner.\n     */\n    function pendingOwner() public view virtual returns (address) {\n        return _pendingOwner;\n    }\n\n    /**\n     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual override onlyOwner {\n        _pendingOwner = newOwner;\n        emit OwnershipTransferStarted(owner(), newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual override {\n        delete _pendingOwner;\n        super._transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev The new owner accepts the ownership transfer.\n     */\n    function acceptOwnership() public virtual {\n        address sender = _msgSender();\n        require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n        _transferOwnership(sender);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// contracts/libs/memory/State.sol\n\n/// State is a memory view over a formatted state payload.\ntype State is uint256;\n\nusing StateLib for State global;\n\n/// # State\n/// State structure represents the state of Origin contract at some point of time.\n/// - State is structured in a way to track the updates of the Origin Merkle Tree.\n/// - State includes root of the Origin Merkle Tree, origin domain and some additional metadata.\n/// ## Origin Merkle Tree\n/// Hash of every sent message is inserted in the Origin Merkle Tree, which changes\n/// the value of Origin Merkle Root (which is the root for the mentioned tree).\n/// - Origin has a single Merkle Tree for all messages, regardless of their destination domain.\n/// - This leads to Origin state being updated if and only if a message was sent in a block.\n/// - Origin contract is a \"source of truth\" for states: a state is considered \"valid\" in its Origin,\n/// if it matches the state of the Origin contract after the N-th (nonce) message was sent.\n///\n/// # Memory layout of State fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                    |\n/// | ---------- | ----------- | ------- | ----- | ------------------------------ |\n/// | [000..032) | root        | bytes32 | 32    | Root of the Origin Merkle Tree |\n/// | [032..036) | origin      | uint32  | 4     | Domain where Origin is located |\n/// | [036..040) | nonce       | uint32  | 4     | Amount of sent messages        |\n/// | [040..045) | blockNumber | uint40  | 5     | Block of last sent message     |\n/// | [045..050) | timestamp   | uint40  | 5     | Time of last sent message      |\n/// | [050..062) | gasData     | uint96  | 12    | Gas data for the chain         |\n///\n/// @dev State could be used to form a Snapshot to be signed by a Guard or a Notary.\nlibrary StateLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_ROOT = 0;\n    uint256 private constant OFFSET_ORIGIN = 32;\n    uint256 private constant OFFSET_NONCE = 36;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 40;\n    uint256 private constant OFFSET_TIMESTAMP = 45;\n    uint256 private constant OFFSET_GAS_DATA = 50;\n\n    // ═══════════════════════════════════════════════════ STATE ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted State payload with provided fields\n     * @param root_         New merkle root\n     * @param origin_       Domain of Origin's chain\n     * @param nonce_        Nonce of the merkle root\n     * @param blockNumber_  Block number when root was saved in Origin\n     * @param timestamp_    Block timestamp when root was saved in Origin\n     * @param gasData_      Gas data for the chain\n     * @return Formatted state\n     */\n    function formatState(\n        bytes32 root_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_,\n        GasData gasData_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(root_, origin_, nonce_, blockNumber_, timestamp_, gasData_);\n    }\n\n    /**\n     * @notice Returns a State view over the given payload.\n     * @dev Will revert if the payload is not a state.\n     */\n    function castToState(bytes memory payload) internal pure returns (State) {\n        return castToState(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a State view.\n     * @dev Will revert if the memory view is not over a state.\n     */\n    function castToState(MemView memView) internal pure returns (State) {\n        if (!isState(memView)) revert UnformattedState();\n        return State.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted State.\n    function isState(MemView memView) internal pure returns (bool) {\n        return memView.len() == STATE_LENGTH;\n    }\n\n    /// @notice Returns the hash of a State, that could be later signed by a Guard to signal\n    /// that the state is invalid.\n    function hashInvalid(State state) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(stateInvalidSalt, keccak(state))\n        return state.unwrap().keccakSalted(STATE_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(State state) internal pure returns (MemView) {\n        return MemView.wrap(State.unwrap(state));\n    }\n\n    /// @notice Compares two State structures.\n    function equals(State a, State b) internal pure returns (bool) {\n        // Length of a State payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═══════════════════════════════════════════════ STATE HASHING ═══════════════════════════════════════════════════\n\n    /// @notice Returns the hash of the State.\n    /// @dev We are using the Merkle Root of a tree with two leafs (see below) as state hash.\n    function leaf(State state) internal pure returns (bytes32) {\n        (bytes32 leftLeaf_, bytes32 rightLeaf_) = state.subLeafs();\n        // Final hash is the parent of these leafs\n        return keccak256(bytes.concat(leftLeaf_, rightLeaf_));\n    }\n\n    /// @notice Returns \"sub-leafs\" of the State. Hash of these \"sub leafs\" is going to be used\n    /// as a \"state leaf\" in the \"Snapshot Merkle Tree\".\n    /// This enables proving that leftLeaf = (root, origin) was a part of the \"Snapshot Merkle Tree\",\n    /// by combining `rightLeaf` with the remainder of the \"Snapshot Merkle Proof\".\n    function subLeafs(State state) internal pure returns (bytes32 leftLeaf_, bytes32 rightLeaf_) {\n        MemView memView = state.unwrap();\n        // Left leaf is (root, origin)\n        leftLeaf_ = memView.prefix({len_: OFFSET_NONCE}).keccak();\n        // Right leaf is (metadata), or (nonce, blockNumber, timestamp)\n        rightLeaf_ = memView.sliceFrom({index_: OFFSET_NONCE}).keccak();\n    }\n\n    /// @notice Returns the left \"sub-leaf\" of the State.\n    function leftLeaf(bytes32 root_, uint32 origin_) internal pure returns (bytes32) {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(root_, origin_));\n    }\n\n    /// @notice Returns the right \"sub-leaf\" of the State.\n    function rightLeaf(uint32 nonce_, uint40 blockNumber_, uint40 timestamp_, GasData gasData_)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(nonce_, blockNumber_, timestamp_, gasData_));\n    }\n\n    // ═══════════════════════════════════════════════ STATE SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns a historical Merkle root from the Origin contract.\n    function root(State state) internal pure returns (bytes32) {\n        return state.unwrap().index({index_: OFFSET_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns domain of chain where the Origin contract is deployed.\n    function origin(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns nonce of Origin contract at the time, when `root` was the Merkle root.\n    function nonce(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when `root` was saved in Origin.\n    function blockNumber(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when `root` was saved in Origin.\n    /// @dev This is the timestamp according to the origin chain.\n    function timestamp(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n\n    /// @notice Returns gas data for the chain.\n    function gasData(State state) internal pure returns (GasData) {\n        return GasDataLib.wrapGasData(state.unwrap().indexUint({index_: OFFSET_GAS_DATA, bytes_: GAS_DATA_LENGTH}));\n    }\n}\n\n// contracts/libs/memory/BaseMessage.sol\n\n/// BaseMessage is a memory view over the base message supported by Origin-Destination\ntype BaseMessage is uint256;\n\nusing BaseMessageLib for BaseMessage global;\n\n/// BaseMessage structure represents a base message sent via the Origin-Destination contracts.\n/// - It only contains data relevant to the base message, the rest of data is encoded in the message header.\n/// - `sender` and `recipient` for EVM chains are EVM addresses casted to bytes32, while preserving left-alignment.\n/// - `tips` and `request` parameters are specified by a message sender\n/// \u003e Origin will calculate minimum tips for given request and content length, and will reject messages with tips\n/// lower than that.\n///\n/// # Memory layout of BaseMessage fields\n///\n/// | Position   | Field     | Type    | Bytes | Description                            |\n/// | ---------- | --------- | ------- | ----- | -------------------------------------- |\n/// | [000..032) | tips      | uint256 | 32    | Encoded tips paid on origin chain      |\n/// | [032..064) | sender    | bytes32 | 32    | Sender address on origin chain         |\n/// | [064..096) | recipient | bytes32 | 32    | Recipient address on destination chain |\n/// | [096..116) | request   | uint160 | 20    | Encoded request for message execution  |\n/// | [104..AAA) | content   | bytes   | ??    | Content to be passed to recipient      |\nlibrary BaseMessageLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_TIPS = 0;\n    uint256 private constant OFFSET_SENDER = 32;\n    uint256 private constant OFFSET_RECIPIENT = 64;\n    uint256 private constant OFFSET_REQUEST = OFFSET_RECIPIENT + TIPS_LENGTH;\n    uint256 private constant OFFSET_CONTENT = OFFSET_REQUEST + REQUEST_LENGTH;\n\n    // ═══════════════════════════════════════════════ BASE MESSAGE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted BaseMessage payload with provided fields.\n     * @param tips_         Encoded tips information\n     * @param sender_       Sender address on origin chain\n     * @param recipient_    Recipient address on destination chain\n     * @param request_      Encoded request for message execution\n     * @param content_      Raw content to be passed to recipient on destination chain\n     * @return Formatted base message\n     */\n    function formatBaseMessage(Tips tips_, bytes32 sender_, bytes32 recipient_, Request request_, bytes memory content_)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return abi.encodePacked(tips_, sender_, recipient_, request_, content_);\n    }\n\n    /**\n     * @notice Returns a BaseMessage view over the given payload.\n     * @dev Will revert if the payload is not a base message.\n     */\n    function castToBaseMessage(bytes memory payload) internal pure returns (BaseMessage) {\n        return castToBaseMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a BaseMessage view.\n     * @dev Will revert if the memory view is not over a base message payload.\n     */\n    function castToBaseMessage(MemView memView) internal pure returns (BaseMessage) {\n        if (!isBaseMessage(memView)) revert UnformattedBaseMessage();\n        return BaseMessage.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted BaseMessage.\n    function isBaseMessage(MemView memView) internal pure returns (bool) {\n        // Check if sender, recipient, tips fields exist\n        return (memView.len() \u003e= OFFSET_CONTENT);\n        // Content could be empty, so we don't check that\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(BaseMessage baseMessage) internal pure returns (MemView) {\n        return MemView.wrap(BaseMessage.unwrap(baseMessage));\n    }\n\n    /// @notice Returns baseMessage's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        // We hash \"tips\" and \"everything but tips\" to make tips proofs easier to verify\n        return MerkleMath.getParent(baseMessage.tips().leaf(), baseMessage.bodyLeaf());\n    }\n\n    /// @notice Returns hash for the \"everything but tips\" part of the base message.\n    function bodyLeaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_SENDER}).keccak();\n    }\n\n    // ═══════════════════════════════════════════ BASE MESSAGE SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips paid on origin chain.\n    function tips(BaseMessage baseMessage) internal pure returns (Tips) {\n        return TipsLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_TIPS, bytes_: TIPS_LENGTH})));\n    }\n\n    /// @notice Returns sender address on origin chain.\n    function sender(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_SENDER, bytes_: 32});\n    }\n\n    /// @notice Returns recipient address on destination chain.\n    function recipient(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_RECIPIENT, bytes_: 32});\n    }\n\n    /// @notice Returns an encoded request for message execution on destination chain.\n    function request(BaseMessage baseMessage) internal pure returns (Request) {\n        return RequestLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_REQUEST, bytes_: REQUEST_LENGTH})));\n    }\n\n    /// @notice Returns an untyped memory view over the content to be passed to recipient.\n    function content(BaseMessage baseMessage) internal pure returns (MemView) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_CONTENT});\n    }\n}\n\n// contracts/base/MessagingBase.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for all messaging contracts.\n * - Provides context on the local chain's domain.\n * - Provides ownership functionality.\n * - Will be providing pausing functionality when it is implemented.\n */\nabstract contract MessagingBase is MultiCallable, Versioned, Ownable2StepUpgradeable {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @notice Domain of the local chain, set once upon contract creation\n    uint32 public immutable localDomain;\n    // @notice Domain of the Synapse chain, set once upon contract creation\n    uint32 public immutable synapseDomain;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev gap for upgrade safety\n    uint256[50] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    constructor(string memory version_, uint32 synapseDomain_) Versioned(version_) {\n        localDomain = ChainContext.chainId();\n        synapseDomain = synapseDomain_;\n    }\n\n    // TODO: Implement pausing\n\n    /**\n     * @dev Should be impossible to renounce ownership;\n     * we override OpenZeppelin OwnableUpgradeable's\n     * implementation of renounceOwnership to make it a no-op\n     */\n    function renounceOwnership() public override onlyOwner {} //solhint-disable-line no-empty-blocks\n}\n\n// contracts/libs/memory/Message.sol\n\n/// Message is a memory over over a formatted message payload.\ntype Message is uint256;\n\nusing MessageLib for Message global;\n\n/// Library for formatting the various messages supported by Origin and Destination.\n///\n/// # Message memory layout\n///\n/// | Position   | Field  | Type    | Bytes | Description                                             |\n/// | ---------- | ------ | ------- | ----- | ------------------------------------------------------- |\n/// | [000..017) | header | uint136 | 17    | Encoded general routing information for the message     |\n/// | [017..AAA) | body   | bytes   | ??    | Formatted payload (according to flag) with message body |\nlibrary MessageLib {\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MemViewLib for bytes;\n    using HeaderLib for MemView;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_HEADER = 0;\n    uint256 private constant OFFSET_BODY = OFFSET_HEADER + HEADER_LENGTH;\n\n    // ══════════════════════════════════════════════════ MESSAGE ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns formatted message with provided fields.\n     * @param header_   Encoded general routing information for the message\n     * @param body_     Formatted payload (according to flag) with message body\n     * @return Formatted message\n     */\n    function formatMessage(Header header_, bytes memory body_) internal pure returns (bytes memory) {\n        return abi.encodePacked(header_, body_);\n    }\n\n    /**\n     * @notice Returns a Message view over for the given payload.\n     * @dev Will revert if the payload is not a message payload.\n     */\n    function castToMessage(bytes memory payload) internal pure returns (Message) {\n        return castToMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Message view.\n     * @dev Will revert if the memory view is not over a message payload.\n     */\n    function castToMessage(MemView memView) internal pure returns (Message) {\n        if (!isMessage(memView)) revert UnformattedMessage();\n        return Message.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Message.\n     */\n    function isMessage(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Check if headers exist in the payload\n        if (length \u003c OFFSET_BODY) return false;\n        // Check that Header is valid\n        uint256 paddedHeader = _header(memView);\n        if (!HeaderLib.isHeader(paddedHeader)) return false;\n        // Check that body is formatted according to the flag\n        // Only Base/Manager message flags exist\n        if (HeaderLib.wrapPadded(paddedHeader).flag() == MessageFlag.Base) {\n            // Check if body is a formatted base message\n            return _body(memView).isBaseMessage();\n        } else {\n            // Check if body is a formatted calldata for AgentManager call\n            return _body(memView).isCallData();\n        }\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Message message) internal pure returns (MemView) {\n        return MemView.wrap(Message.unwrap(message));\n    }\n\n    /// @notice Returns message's hash: a leaf to be inserted in the Merkle tree.\n    function leaf(Message message) internal pure returns (bytes32) {\n        // We hash header and body separately to make message proofs easier to verify\n        Header header_ = message.header();\n        // Only Base/Manager message flags exist\n        if (header_.flag() == MessageFlag.Base) {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToBaseMessage().leaf());\n        } else {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToCallData().leaf());\n        }\n    }\n\n    // ══════════════════════════════════════════════ MESSAGE SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns message's encoded header field.\n    function header(Message message) internal pure returns (Header) {\n        return HeaderLib.wrapPadded((message.unwrap().indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH})));\n    }\n\n    /// @notice Returns message's body field as an untyped memory view.\n    function body(Message message) internal pure returns (MemView) {\n        MemView memView = message.unwrap();\n        return _body(memView);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns message's padded header without checking that it is a valid header.\n    function _header(MemView memView) private pure returns (uint256) {\n        return memView.indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH});\n    }\n\n    /// @dev Returns an untyped memory view over the body field without checking\n    /// if the whole payload or the body are properly formatted.\n    function _body(MemView memView) private pure returns (MemView) {\n        return memView.sliceFrom({index_: OFFSET_BODY});\n    }\n}\n\n// contracts/base/AgentSecured.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for messaging contracts that are secured by the agent manager.\n * `AgentSecured` relies on `AgentManager` to provide the following functionality:\n * - Keep track of agents and their statuses.\n * - Pass agent-signed statements that were verified by the agent manager.\n * - These statements are considered valid indefinitely, unless the agent is disputed.\n * - Disputes are opened and resolved by the agent manager.\n * \u003e `AgentSecured` implementation should never use statements signed by agents that are disputed.\n */\nabstract contract AgentSecured is MessagingBase, IAgentSecured {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    address public immutable agentManager;\n\n    /// @inheritdoc IAgentSecured\n    address public immutable inbox;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    // (agent index =\u003e their dispute status: flag, openedAt, resolvedAt)\n    mapping(uint32 =\u003e DisputeStatus) internal _disputes;\n\n    /// @dev gap for upgrade safety\n    uint256[49] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    modifier onlyAgentManager() {\n        if (msg.sender != agentManager) revert CallerNotAgentManager();\n        _;\n    }\n\n    modifier onlyInbox() {\n        if (msg.sender != inbox) revert CallerNotInbox();\n        _;\n    }\n\n    constructor(string memory version_, uint32 synapseDomain_, address agentManager_, address inbox_)\n        MessagingBase(version_, synapseDomain_)\n    {\n        agentManager = agentManager_;\n        inbox = inbox_;\n    }\n\n    // ════════════════════════════════════════════ ONLY AGENT MANAGER ═════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external onlyAgentManager {\n        uint40 openedAt = ChainContext.blockTimestamp();\n        DisputeStatus memory status = DisputeStatus({flag: DisputeFlag.Pending, openedAt: openedAt, resolvedAt: 0});\n        _disputes[guardIndex] = status;\n        _disputes[notaryIndex] = status;\n    }\n\n    /// @inheritdoc IAgentSecured\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external onlyAgentManager {\n        // Update the dispute status of the slashed agent first.\n        uint40 resolvedAt = ChainContext.blockTimestamp();\n        _disputes[slashedIndex].flag = DisputeFlag.Slashed;\n        _disputes[slashedIndex].resolvedAt = resolvedAt;\n        // Mark the rival agent as not disputed, if there was an ongoing dispute.\n        if (rivalIndex != 0) {\n            _disputes[rivalIndex].flag = DisputeFlag.None;\n            _disputes[rivalIndex].resolvedAt = resolvedAt;\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function agentStatus(address agent) external view returns (AgentStatus memory) {\n        return _agentStatus(agent);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status) {\n        return _getAgent(index);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory) {\n        return _disputes[agentIndex];\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns status of the given agent: (flag, domain, index).\n    function _agentStatus(address agent) internal view returns (AgentStatus memory) {\n        return IAgentManager(agentManager).agentStatus(agent);\n    }\n\n    /// @dev Returns agent and their status for a given agent index. Returns zero values for non existing indexes.\n    function _getAgent(uint256 index) internal view returns (address agent, AgentStatus memory status) {\n        return IAgentManager(agentManager).getAgent(index);\n    }\n\n    /// @dev Checks if a Dispute exists for the given Notary. This function returns true, if\n    /// Notary is in ongoing Dispute, or if Dispute was resolved not in Notary's favor.\n    /// In both cases we can't trust Notary's data.\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeExists(uint32 notaryIndex) internal view returns (bool) {\n        return _disputes[notaryIndex].flag != DisputeFlag.None;\n    }\n\n    /// @dev Checks if a Notary recently won a Dispute and is still in the \"post-dispute\" timeout period.\n    /// In this period we still can't trust Notary's data, though we can optimistically assume that\n    /// that the data will be correct after the timeout (assuming no new Disputes are opened).\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeTimeout(uint32 notaryIndex) internal view returns (bool) {\n        DisputeStatus memory status = _disputes[notaryIndex];\n        // Exit early if Notary is in ongoing Dispute / slashed.\n        if (status.flag != DisputeFlag.None) return false;\n        // Check if Notary has been in any Dispute at all.\n        if (status.openedAt == 0) return false;\n        // Otherwise check if the Dispute timeout is still active.\n        return block.timestamp \u003c status.resolvedAt + DISPUTE_TIMEOUT_NOTARY;\n    }\n}\n\n// contracts/hubs/StateHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StateHub` is a parent contract for `Origin`. It is responsible for the following:\n/// - Keeping track of the historical Origin Merkle Tree containing all the message hashes.\n/// - Keeping track of the historical Origin States, as well as verifying their validity.\nabstract contract StateHub is AgentSecured, StateHubEvents, IStateHub {\n    using SafeCast for uint256;\n    using StateLib for bytes;\n\n    struct OriginState {\n        uint40 blockNumber;\n        uint40 timestamp;\n        GasData gasData;\n    }\n    // Bits left for tight packing: 80\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Historical Merkle Tree\n    /// Note: Takes two storage slots\n    HistoricalTree private _tree;\n\n    /// @dev All historical contract States\n    OriginState[] private _originStates;\n\n    /// @dev gap for upgrade safety\n    uint256[47] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IStateHub\n    function isValidState(bytes memory statePayload) external view returns (bool isValid) {\n        // This will revert if payload is not a formatted state\n        State state = statePayload.castToState();\n        return _isValidState(state);\n    }\n\n    /// @inheritdoc IStateHub\n    function statesAmount() external view returns (uint256) {\n        return _originStates.length;\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestLatestState() external view returns (bytes memory stateData) {\n        // This never underflows, assuming the contract was initialized\n        return suggestState(_nextNonce() - 1);\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestState(uint32 nonce) public view returns (bytes memory stateData) {\n        // This will revert if nonce is out of range\n        bytes32 root = _tree.root(nonce);\n        return _formatOriginState(_originStates[nonce], root, localDomain, nonce);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Initializes the saved states list by inserting a state for an empty Merkle Tree.\n    function _initializeStates() internal {\n        // This should only be called once, when the contract is initialized\n        // This will revert if _tree.roots is non-empty\n        bytes32 savedRoot = _tree.initializeRoots();\n        // Save root for empty merkle _tree with block number and timestamp of initialization\n        _saveState(savedRoot, _toOriginState());\n    }\n\n    /// @dev Inserts leaf into the Merkle Tree and saves the updated origin State.\n    function _insertAndSave(bytes32 leaf) internal {\n        bytes32 newRoot = _tree.insert(leaf);\n        _saveState(newRoot, _toOriginState());\n    }\n\n    /// @dev Saves an updated state of the Origin contract\n    function _saveState(bytes32 root, OriginState memory state) internal {\n        uint32 nonce = _nextNonce();\n        _originStates.push(state);\n        // Emit event with raw state data\n        emit StateSaved(_formatOriginState(state, root, localDomain, nonce));\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns nonce of the next sent message: the amount of saved States so far.\n    /// This always equals to \"total amount of sent messages\" plus 1.\n    function _nextNonce() internal view returns (uint32) {\n        // TODO: consider using more than 32 bits for origin nonces\n        return _originStates.length.toUint32();\n    }\n\n    /// @dev Checks if a state is valid, i.e. if it matches the historical one.\n    /// Reverts, if state refers to another Origin contract.\n    function _isValidState(State state) internal view returns (bool) {\n        // Check if state refers to this contract\n        if (state.origin() != localDomain) revert IncorrectOriginDomain();\n        // Check if nonce exists\n        uint32 nonce = state.nonce();\n        if (nonce \u003e= _originStates.length) return false;\n        // Check if state root matches the historical one\n        if (state.root() != _tree.root(nonce)) return false;\n        // Check if state metadata matches the historical one\n        return _areEqual(state, _originStates[nonce]);\n    }\n\n    // ═════════════════════════════════════════════ STRUCT FORMATTING ═════════════════════════════════════════════════\n\n    /// @dev Returns a formatted payload for a stored OriginState.\n    function _formatOriginState(OriginState memory originState, bytes32 root, uint32 origin, uint32 nonce)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return StateLib.formatState({\n            root_: root,\n            origin_: origin,\n            nonce_: nonce,\n            blockNumber_: originState.blockNumber,\n            timestamp_: originState.timestamp,\n            gasData_: originState.gasData\n        });\n    }\n\n    /// @dev Child contract should implement the logic for getting the current gas data from the gas oracle\n    /// to be saved as part of the Origin State.\n    // solhint-disable-next-line ordering\n    function _fetchGasData() internal view virtual returns (GasData);\n\n    /// @dev Returns a OriginState struct to save in the contract.\n    function _toOriginState() internal view returns (OriginState memory originState) {\n        originState.blockNumber = ChainContext.blockNumber();\n        originState.timestamp = ChainContext.blockTimestamp();\n        originState.gasData = _fetchGasData();\n    }\n\n    /// @dev Checks that a state and its Origin representation are equal.\n    function _areEqual(State state, OriginState memory originState) internal pure returns (bool) {\n        return state.blockNumber() == originState.blockNumber \u0026\u0026 state.timestamp() == originState.timestamp;\n    }\n}\n\n// contracts/Origin.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Origin` contract is used for sending messages to remote chains. It is done\n/// by inserting the message hashes into the Origin Merkle, which makes it possible to\n/// prove that message was sent using the Merkle proof against the Origin Merkle Root. This essentially\n/// compresses the list of messages into a single 32-byte value that needs to be stored on the destination chain.\n/// `Origin` is responsible for the following:\n/// - Formatting the sent message payloads, and inserting their hashes into the Origin Merkle Tree.\n/// - Keeping track of its own historical states (see parent contract `StateHub`).\n/// - Enforcing minimum tip values for sent base messages based on the provided execution requests.\n/// - Distributing the collected tips upon request from a local `AgentManager` contract.\ncontract Origin is StateHub, OriginEvents, InterfaceOrigin {\n    using MemViewLib for bytes;\n    using MessageLib for bytes;\n    using TipsLib for bytes;\n    using TypeCasts for address;\n\n    address public immutable gasOracle;\n\n    modifier onlyRemoteDestination(uint32 destination) {\n        if (destination == localDomain) revert IncorrectDestinationDomain();\n        _;\n    }\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_, address gasOracle_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {\n        gasOracle = gasOracle_;\n    }\n\n    /// @notice Initializes Origin contract:\n    /// - msg.sender is set as contract owner\n    /// - State of \"empty merkle tree\" is saved\n    function initialize() external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize \"states\": state of an \"empty merkle tree\" is saved\n        _initializeStates();\n    }\n\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable onlyRemoteDestination(destination) returns (uint32 messageNonce, bytes32 messageHash) {\n        // Check that content is not too large\n        if (content.length \u003e MAX_CONTENT_BYTES) revert ContentLengthTooBig();\n        // This will revert if msg.value is lower than value of minimum tips\n        Tips tips = _getMinimumTips(destination, paddedRequest, content.length).matchValue(msg.value);\n        Request request = RequestLib.wrapPadded(paddedRequest);\n        // Format the BaseMessage body\n        bytes memory body = BaseMessageLib.formatBaseMessage({\n            sender_: msg.sender.addressToBytes32(),\n            recipient_: recipient,\n            tips_: tips,\n            request_: request,\n            content_: content\n        });\n        // Send the message\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Base, body);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        onlyAgentManager\n        onlyRemoteDestination(destination)\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // AgentManager (checked via modifier) is responsible for constructing the calldata payload correctly.\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Manager, payload);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function withdrawTips(address recipient, uint256 amount) external onlyAgentManager {\n        if (address(this).balance \u003c amount) revert InsufficientEthBalance();\n        (bool success,) = recipient.call{value: amount}(\"\");\n        if (!success) revert EthTransferFailed();\n        emit TipWithdrawalCompleted(recipient, amount);\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue)\n    {\n        return _getMinimumTips(destination, paddedRequest, contentLength).value();\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Sends the given message to the specified destination. Message hash is inserted\n    /// into the Origin Merkle Tree, which will enable message execution on destination chain.\n    function _sendMessage(uint32 destination, uint32 optimisticPeriod, MessageFlag flag, bytes memory body)\n        internal\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // Format the message header\n        messageNonce = _nextNonce();\n        Header header = flag.encodeHeader({\n            origin_: localDomain,\n            nonce_: messageNonce,\n            destination_: destination,\n            optimisticPeriod_: optimisticPeriod\n        });\n        // Format the full message payload\n        bytes memory msgPayload = MessageLib.formatMessage(header, body);\n        // Insert new leaf into the Origin Merkle Tree and save the updated state\n        messageHash = msgPayload.castToMessage().leaf();\n        _insertAndSave(messageHash);\n        // Emit event with message information\n        emit Sent(messageHash, messageNonce, destination, msgPayload);\n        // Update the gas oracle data. We do this after the provided tips are checked so that\n        // the provided message is sent in the event that the gas oracle data is updated to a higher value.\n        InterfaceGasOracle(gasOracle).updateGasData(destination);\n        // TODO: consider doing this before the message is sent, while adjusting GasOracle.getMinimumTips() to\n        // use the pending gas oracle data.\n    }\n\n    /// @dev Returns the minimum tips for sending a message to the given destination with the given request and content.\n    function _getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        internal\n        view\n        returns (Tips)\n    {\n        return\n            TipsLib.wrapPadded(InterfaceGasOracle(gasOracle).getMinimumTips(destination, paddedRequest, contentLength));\n    }\n\n    /// @dev Gets the current gas data from the gas oracle to be saved as part of the Origin State.\n    function _fetchGasData() internal view override returns (GasData) {\n        return GasDataLib.wrapGasData(InterfaceGasOracle(gasOracle).getGasData());\n    }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[{"internalType":"uint32","name":"domain","type":"uint32"}],"name":"getDecodedGasData","outputs":[{"internalType":"uint256","name":"gasPrice","type":"uint256"},{"internalType":"uint256","name":"dataPrice","type":"uint256"},{"internalType":"uint256","name":"execBuffer","type":"uint256"},{"internalType":"uint256","name":"amortAttCost","type":"uint256"},{"internalType":"uint256","name":"etherPrice","type":"uint256"},{"internalType":"uint256","name":"markup","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getGasData","outputs":[{"internalType":"uint256","name":"paddedGasData","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"destination","type":"uint32"},{"internalType":"uint256","name":"paddedRequest","type":"uint256"},{"internalType":"uint256","name":"contentLength","type":"uint256"}],"name":"getMinimumTips","outputs":[{"internalType":"uint256","name":"paddedTips","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"domain","type":"uint32"}],"name":"updateGasData","outputs":[],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{"getDecodedGasData(uint32)":{"notice":"Returns the gas data for the given domain, in the decoded format."},"getGasData()":{"notice":"Returns the gas data for the local chain."},"getMinimumTips(uint32,uint256,uint256)":{"notice":"Returns the minimum tips for sending a message to a given destination."},"updateGasData(uint32)":{"notice":"Fetches the latest gas data for the chain from `Destination` contract, and uses it to update the oracle values for the requested chain."}},"version":1},"developerDoc":{"kind":"dev","methods":{"getDecodedGasData(uint32)":{"params":{"domain":"Domain of chain to get gas data for"},"returns":{"amortAttCost":"Amortized cost for attestation submission (in Wei)","dataPrice":"   Calldata price (in Wei per byte of content)","etherPrice":"  Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)","execBuffer":"  Tx fee safety buffer for message execution (in Wei)","gasPrice":"    Gas price for the chain (in Wei per gas unit)","markup":"      Markup for the message execution (in BWAD)"}},"getMinimumTips(uint32,uint256,uint256)":{"params":{"contentLength":"The length of the message content","destination":"Domain of destination chain","paddedRequest":"Padded encoded message execution request on destination chain"},"returns":{"paddedTips":"      Padded encoded minimum tips information"}},"updateGasData(uint32)":{"params":{"domain":"Domain to update the gas data for"}}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"domain\",\"type\":\"uint32\"}],\"name\":\"getDecodedGasData\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"gasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"dataPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"execBuffer\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amortAttCost\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"etherPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"markup\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getGasData\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"paddedGasData\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"destination\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"paddedRequest\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"contentLength\",\"type\":\"uint256\"}],\"name\":\"getMinimumTips\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"paddedTips\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"domain\",\"type\":\"uint32\"}],\"name\":\"updateGasData\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"getDecodedGasData(uint32)\":{\"params\":{\"domain\":\"Domain of chain to get gas data for\"},\"returns\":{\"amortAttCost\":\"Amortized cost for attestation submission (in Wei)\",\"dataPrice\":\"   Calldata price (in Wei per byte of content)\",\"etherPrice\":\"  Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\",\"execBuffer\":\"  Tx fee safety buffer for message execution (in Wei)\",\"gasPrice\":\"    Gas price for the chain (in Wei per gas unit)\",\"markup\":\"      Markup for the message execution (in BWAD)\"}},\"getMinimumTips(uint32,uint256,uint256)\":{\"params\":{\"contentLength\":\"The length of the message content\",\"destination\":\"Domain of destination chain\",\"paddedRequest\":\"Padded encoded message execution request on destination chain\"},\"returns\":{\"paddedTips\":\"      Padded encoded minimum tips information\"}},\"updateGasData(uint32)\":{\"params\":{\"domain\":\"Domain to update the gas data for\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"getDecodedGasData(uint32)\":{\"notice\":\"Returns the gas data for the given domain, in the decoded format.\"},\"getGasData()\":{\"notice\":\"Returns the gas data for the local chain.\"},\"getMinimumTips(uint32,uint256,uint256)\":{\"notice\":\"Returns the minimum tips for sending a message to a given destination.\"},\"updateGasData(uint32)\":{\"notice\":\"Fetches the latest gas data for the chain from `Destination` contract, and uses it to update the oracle values for the requested chain.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Origin.sol\":\"InterfaceGasOracle\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Origin.sol\":{\"keccak256\":\"0x96775924f147f3d1f8df8cdf56731fe52a15af8d8e12e608efb8158c112b18cd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e642a27f5fab3c62b4c02e9754e9e42b1cf2e5381dbea9d3d106d23b7772ebe6\",\"dweb:/ipfs/QmUwn7ZyBvPkjnMuK8ZMSexBUdNQnVtxwyoAyT4DXLQjra\"]}},\"version\":1}"},"hashes":{"getDecodedGasData(uint32)":"556517b7","getGasData()":"34926b29","getMinimumTips(uint32,uint256,uint256)":"72010a93","updateGasData(uint32)":"867baea5"}},"solidity/Origin.sol:InterfaceOrigin":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/OriginEvents.sol\n\n/// @notice A collection of events emitted by the Origin contract\nabstract contract OriginEvents {\n    /**\n     * @notice Emitted when a new message is sent.\n     * @param messageHash   Hash of message; the leaf inserted to the Merkle tree for the message\n     * @param nonce         Nonce of sent message (starts from 1)\n     * @param destination   Destination domain\n     * @param message       Raw bytes of message\n     */\n    event Sent(bytes32 indexed messageHash, uint32 indexed nonce, uint32 indexed destination, bytes message);\n\n    /**\n     * @notice Emitted when a tip withdrawal is completed.\n     * @param actor     Actor address\n     * @param tip       Tip value, denominated in local domain's wei\n     */\n    event TipWithdrawalCompleted(address actor, uint256 tip);\n}\n\n// contracts/events/StateHubEvents.sol\n\n/// @notice A collection of events emitted by the StateHub contract\nabstract contract StateHubEvents {\n    /**\n     * @notice Emitted when a new Origin State is saved after a message was sent.\n     * @param state     Raw payload with state data\n     */\n    event StateSaved(bytes state);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n    /**\n     * @notice Check that a given state is valid: matches the historical state of Origin contract.\n     * Note: any Agent including an invalid state in their snapshot will be slashed\n     * upon providing the snapshot and agent signature for it to Origin contract.\n     * @dev Will revert if any of these is true:\n     *  - State payload is not properly formatted.\n     * @param statePayload      Raw payload with state data\n     * @return isValid          Whether the provided state is valid\n     */\n    function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns the amount of saved states so far.\n     * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n     */\n    function statesAmount() external view returns (uint256);\n\n    /**\n     * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @return statePayload     Raw payload with the latest state data\n     */\n    function suggestLatestState() external view returns (bytes memory statePayload);\n\n    /**\n     * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @param nonce             Historical nonce to form a state\n     * @return statePayload     Raw payload with historical state data\n     */\n    function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/InterfaceGasOracle.sol\n\ninterface InterfaceGasOracle {\n    /**\n     * @notice Fetches the latest gas data for the chain from `Destination` contract,\n     * and uses it to update the oracle values for the requested chain.\n     * @param domain    Domain to update the gas data for\n     */\n    function updateGasData(uint32 domain) external;\n\n    /**\n     * @notice Returns the gas data for the local chain.\n     */\n    function getGasData() external view returns (uint256 paddedGasData);\n\n    /**\n     * @notice Returns the gas data for the given domain, in the decoded format.\n     * @param domain        Domain of chain to get gas data for\n     * @return gasPrice     Gas price for the chain (in Wei per gas unit)\n     * @return dataPrice    Calldata price (in Wei per byte of content)\n     * @return execBuffer   Tx fee safety buffer for message execution (in Wei)\n     * @return amortAttCost Amortized cost for attestation submission (in Wei)\n     * @return etherPrice   Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n     * @return markup       Markup for the message execution (in BWAD)\n     */\n    function getDecodedGasData(uint32 domain)\n        external\n        view\n        returns (\n            uint256 gasPrice,\n            uint256 dataPrice,\n            uint256 execBuffer,\n            uint256 amortAttCost,\n            uint256 etherPrice,\n            uint256 markup\n        );\n\n    /**\n     * @notice Returns the minimum tips for sending a message to a given destination.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return paddedTips       Padded encoded minimum tips information\n     */\n    function getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 paddedTips);\n}\n\n// contracts/interfaces/InterfaceOrigin.sol\n\ninterface InterfaceOrigin {\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /**\n     * @notice Send a message to the recipient located on destination domain.\n     * @dev Recipient has to conform to IMessageRecipient interface, otherwise message won't be delivered.\n     * Will revert if any of these is true:\n     * - `destination` is equal to contract's local domain\n     * - `content` length is greater than `MAX_CONTENT_BYTES`\n     * - `msg.value` is lower than value of minimum tips for the given message\n     * @param destination           Domain of destination chain\n     * @param recipient             Address of recipient on destination chain as bytes32\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param paddedRequest         Padded encoded message execution request on destination chain\n     * @param content               Raw bytes content of message\n     * @return messageNonce         Nonce of the sent message\n     * @return messageHash          Hash of the sent message\n     */\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable returns (uint32 messageNonce, bytes32 messageHash);\n\n    /**\n     * @notice Send a manager message to the destination domain.\n     * @dev This could only be called by AgentManager, which takes care of encoding the calldata payload.\n     * Note: (msgOrigin, proofMaturity) security args will be added to payload on the destination chain\n     * so that the AgentManager could verify where the Manager Message came from and how mature is the proof.\n     * Note: function is not payable, as no tips are required for sending a manager message.\n     * Will revert if `destination` is equal to contract's local domain.\n     * @param destination           Domain of destination chain\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param payload               Payload for calling AgentManager on destination chain (with extra security args)\n     */\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        returns (uint32 messageNonce, bytes32 messageHash);\n\n    // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Withdraws locked base message tips to the recipient.\n     * @dev Could only be called by a local AgentManager.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function withdrawTips(address recipient, uint256 amount) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the minimum tips value for sending a message to a given destination.\n     * @dev Using at least `tipsValue` as `msg.value` for `sendBaseMessage()`\n     * will guarantee that the message will be accepted.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return tipsValue        Minimum tips value for a message to be accepted\n     */\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue);\n}\n\n// contracts/libs/Constants.sol\n\n// Here we define common constants to enable their easier reusing later.\n\n// ══════════════════════════════════ MERKLE ═══════════════════════════════════\n/// @dev Height of the Agent Merkle Tree\nuint256 constant AGENT_TREE_HEIGHT = 32;\n/// @dev Height of the Origin Merkle Tree\nuint256 constant ORIGIN_TREE_HEIGHT = 32;\n/// @dev Height of the Snapshot Merkle Tree. Allows up to 64 leafs, e.g. up to 32 states\nuint256 constant SNAPSHOT_TREE_HEIGHT = 6;\n// ══════════════════════════════════ STRUCTS ══════════════════════════════════\n/// @dev See Attestation.sol: (bytes32,bytes32,uint32,uint40,uint40): 32+32+4+5+5\nuint256 constant ATTESTATION_LENGTH = 78;\n/// @dev See GasData.sol: (uint16,uint16,uint16,uint16,uint16,uint16): 2+2+2+2+2+2\nuint256 constant GAS_DATA_LENGTH = 12;\n/// @dev See Receipt.sol: (uint32,uint32,bytes32,bytes32,uint8,address,address,address): 4+4+32+32+1+20+20+20\nuint256 constant RECEIPT_LENGTH = 133;\n/// @dev See State.sol: (bytes32,uint32,uint32,uint40,uint40,GasData): 32+4+4+5+5+len(GasData)\nuint256 constant STATE_LENGTH = 50 + GAS_DATA_LENGTH;\n/// @dev Maximum amount of states in a single snapshot. Each state produces two leafs in the tree\nuint256 constant SNAPSHOT_MAX_STATES = 1 \u003c\u003c (SNAPSHOT_TREE_HEIGHT - 1);\n// ══════════════════════════════════ MESSAGE ══════════════════════════════════\n/// @dev See Header.sol: (uint8,uint32,uint32,uint32,uint32): 1+4+4+4+4\nuint256 constant HEADER_LENGTH = 17;\n/// @dev See Request.sol: (uint96,uint64,uint32): 12+8+4\nuint256 constant REQUEST_LENGTH = 24;\n/// @dev See Tips.sol: (uint64,uint64,uint64,uint64): 8+8+8+8\nuint256 constant TIPS_LENGTH = 32;\n/// @dev The amount of discarded last bits when encoding tip values\nuint256 constant TIPS_GRANULARITY = 32;\n/// @dev Tip values could be only the multiples of TIPS_MULTIPLIER\nuint256 constant TIPS_MULTIPLIER = 1 \u003c\u003c TIPS_GRANULARITY;\n// ══════════════════════════════ STATEMENT SALTS ══════════════════════════════\n/// @dev Salts for signing various statements\nbytes32 constant ATTESTATION_VALID_SALT = keccak256(\"ATTESTATION_VALID_SALT\");\nbytes32 constant ATTESTATION_INVALID_SALT = keccak256(\"ATTESTATION_INVALID_SALT\");\nbytes32 constant RECEIPT_VALID_SALT = keccak256(\"RECEIPT_VALID_SALT\");\nbytes32 constant RECEIPT_INVALID_SALT = keccak256(\"RECEIPT_INVALID_SALT\");\nbytes32 constant SNAPSHOT_VALID_SALT = keccak256(\"SNAPSHOT_VALID_SALT\");\nbytes32 constant STATE_INVALID_SALT = keccak256(\"STATE_INVALID_SALT\");\n// ═════════════════════════════════ PROTOCOL ══════════════════════════════════\n/// @dev Optimistic period for new agent roots in LightManager\nuint32 constant AGENT_ROOT_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Timeout between the agent root could be proposed and resolved in LightManager\nuint32 constant AGENT_ROOT_PROPOSAL_TIMEOUT = 12 hours;\nuint32 constant BONDING_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Amount of time that the Notary will not be considered active after they won a dispute\nuint32 constant DISPUTE_TIMEOUT_NOTARY = 12 hours;\n/// @dev Amount of time without fresh data from Notaries before contract owner can resolve stuck disputes manually\nuint256 constant FRESH_DATA_TIMEOUT = 4 hours;\n/// @dev Maximum bytes per message = 2 KiB (somewhat arbitrarily set to begin)\nuint256 constant MAX_CONTENT_BYTES = 2 * 2 ** 10;\n/// @dev Maximum value for the summit tip that could be set in GasOracle\nuint256 constant MAX_SUMMIT_TIP = 0.01 ether;\n\n// contracts/libs/Errors.sol\n\n// ══════════════════════════════ INVALID CALLER ═══════════════════════════════\n\nerror CallerNotAgentManager();\nerror CallerNotDestination();\nerror CallerNotInbox();\nerror CallerNotSummit();\n\n// ══════════════════════════════ INCORRECT DATA ═══════════════════════════════\n\nerror IncorrectAttestation();\nerror IncorrectAgentDomain();\nerror IncorrectAgentIndex();\nerror IncorrectAgentProof();\nerror IncorrectAgentRoot();\nerror IncorrectDataHash();\nerror IncorrectDestinationDomain();\nerror IncorrectOriginDomain();\nerror IncorrectSnapshotProof();\nerror IncorrectSnapshotRoot();\nerror IncorrectState();\nerror IncorrectStatesAmount();\nerror IncorrectTipsProof();\nerror IncorrectVersionLength();\n\nerror IncorrectNonce();\nerror IncorrectSender();\nerror IncorrectRecipient();\n\nerror FlagOutOfRange();\nerror IndexOutOfRange();\nerror NonceOutOfRange();\n\nerror OutdatedNonce();\n\nerror UnformattedAttestation();\nerror UnformattedAttestationReport();\nerror UnformattedBaseMessage();\nerror UnformattedCallData();\nerror UnformattedCallDataPrefix();\nerror UnformattedMessage();\nerror UnformattedReceipt();\nerror UnformattedReceiptReport();\nerror UnformattedSignature();\nerror UnformattedSnapshot();\nerror UnformattedState();\nerror UnformattedStateReport();\n\n// ═══════════════════════════════ MERKLE TREES ════════════════════════════════\n\nerror LeafNotProven();\nerror MerkleTreeFull();\nerror NotEnoughLeafs();\nerror TreeHeightTooLow();\n\n// ═════════════════════════════ OPTIMISTIC PERIOD ═════════════════════════════\n\nerror BaseClientOptimisticPeriod();\nerror MessageOptimisticPeriod();\nerror SlashAgentOptimisticPeriod();\nerror WithdrawTipsOptimisticPeriod();\nerror ZeroProofMaturity();\n\n// ═══════════════════════════════ AGENT MANAGER ═══════════════════════════════\n\nerror AgentNotGuard();\nerror AgentNotNotary();\n\nerror AgentCantBeAdded();\nerror AgentNotActive();\nerror AgentNotActiveNorUnstaking();\nerror AgentNotFraudulent();\nerror AgentNotUnstaking();\nerror AgentUnknown();\n\nerror AgentRootNotProposed();\nerror AgentRootTimeoutNotOver();\n\nerror NotStuck();\n\nerror DisputeAlreadyResolved();\nerror DisputeNotOpened();\nerror DisputeTimeoutNotOver();\nerror GuardInDispute();\nerror NotaryInDispute();\n\nerror MustBeSynapseDomain();\nerror SynapseDomainForbidden();\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\nerror AlreadyExecuted();\nerror AlreadyFailed();\nerror DuplicatedSnapshotRoot();\nerror IncorrectMagicValue();\nerror GasLimitTooLow();\nerror GasSuppliedTooLow();\n\n// ══════════════════════════════════ ORIGIN ═══════════════════════════════════\n\nerror ContentLengthTooBig();\nerror EthTransferFailed();\nerror InsufficientEthBalance();\n\n// ════════════════════════════════ GAS ORACLE ═════════════════════════════════\n\nerror LocalGasDataNotSet();\nerror RemoteGasDataNotSet();\n\n// ═══════════════════════════════════ TIPS ════════════════════════════════════\n\nerror SummitTipTooHigh();\nerror TipsClaimMoreThanEarned();\nerror TipsClaimZero();\nerror TipsOverflow();\nerror TipsValueTooLow();\n\n// ════════════════════════════════ MEMORY VIEW ════════════════════════════════\n\nerror IndexedTooMuch();\nerror ViewOverrun();\nerror OccupiedMemory();\nerror UnallocatedMemory();\nerror PrecompileOutOfGas();\n\n// ═════════════════════════════════ MULTICALL ═════════════════════════════════\n\nerror MulticallFailed();\n\n// contracts/libs/TypeCasts.sol\n\nlibrary TypeCasts {\n    // alignment preserving cast\n    function addressToBytes32(address addr) internal pure returns (bytes32) {\n        return bytes32(uint256(uint160(addr)));\n    }\n\n    // alignment preserving cast\n    function bytes32ToAddress(bytes32 buf) internal pure returns (address) {\n        return address(uint160(uint256(buf)));\n    }\n}\n\n// contracts/libs/stack/Number.sol\n\n/// Number is a compact representation of uint256, that is fit into 16 bits\n/// with the maximum relative error under 0.4%.\ntype Number is uint16;\n\nusing NumberLib for Number global;\n\n/// # Number\n/// Library for compact representation of uint256 numbers.\n/// - Number is stored using mantissa and exponent, each occupying 8 bits.\n/// - Numbers under 2**8 are stored as `mantissa` with `exponent = 0xFF`.\n/// - Numbers at least 2**8 are approximated as `(256 + mantissa) \u003c\u003c exponent`\n/// \u003e - `0 \u003c= mantissa \u003c 256`\n/// \u003e - `0 \u003c= exponent \u003c= 247` (`256 * 2**248` doesn't fit into uint256)\n/// # Number stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type  | Bytes |\n/// | ---------- | -------- | ----- | ----- |\n/// | (002..001] | mantissa | uint8 | 1     |\n/// | (001..000] | exponent | uint8 | 1     |\n\nlibrary NumberLib {\n    /// @dev Amount of bits to shift to mantissa field\n    uint16 private constant SHIFT_MANTISSA = 8;\n\n    /// @notice For bwad math (binary wad) we use 2**64 as \"wad\" unit.\n    /// @dev We are using not using 10**18 as wad, because it is not stored precisely in NumberLib.\n    uint256 internal constant BWAD_SHIFT = 64;\n    uint256 internal constant BWAD = 1 \u003c\u003c BWAD_SHIFT;\n    /// @notice ~0.1% in bwad units.\n    uint256 internal constant PER_MILLE_SHIFT = BWAD_SHIFT - 10;\n    uint256 internal constant PER_MILLE = 1 \u003c\u003c PER_MILLE_SHIFT;\n\n    /// @notice Compresses uint256 number into 16 bits.\n    function compress(uint256 value) internal pure returns (Number) {\n        // Find `msb` such as `2**msb \u003c= value \u003c 2**(msb + 1)`\n        uint256 msb = mostSignificantBit(value);\n        // We want to preserve 9 bits of precision.\n        // The highest bit is always 1, so we can skip it.\n        // The remaining 8 highest bits are stored as mantissa.\n        if (msb \u003c 8) {\n            // Value is less than 2**8, so we can use value as mantissa with \"-1\" exponent.\n            return _encode(uint8(value), 0xFF);\n        } else {\n            // We use `msb - 8` as exponent otherwise. Note that `exponent \u003e= 0`.\n            unchecked {\n                uint256 exponent = msb - 8;\n                // Shifting right by `msb-8` bits will shift the \"remaining 8 highest bits\" into the 8 lowest bits.\n                // uint8() will truncate the highest bit.\n                return _encode(uint8(value \u003e\u003e exponent), uint8(exponent));\n            }\n        }\n    }\n\n    /// @notice Decompresses 16 bits number into uint256.\n    /// @dev The outcome is an approximation of the original number: `(value - value / 256) \u003c number \u003c= value`.\n    function decompress(Number number) internal pure returns (uint256 value) {\n        // Isolate 8 highest bits as the mantissa.\n        uint256 mantissa = Number.unwrap(number) \u003e\u003e SHIFT_MANTISSA;\n        // This will truncate the highest bits, leaving only the exponent.\n        uint256 exponent = uint8(Number.unwrap(number));\n        if (exponent == 0xFF) {\n            return mantissa;\n        } else {\n            unchecked {\n                return (256 + mantissa) \u003c\u003c (exponent);\n            }\n        }\n    }\n\n    /// @dev Returns the most significant bit of `x`\n    /// https://solidity-by-example.org/bitwise/\n    function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\n        // To find `msb` we determine it bit by bit, starting from the highest one.\n        // `0 \u003c= msb \u003c= 255`, so we start from the highest bit, 1\u003c\u003c7 == 128.\n        // If `x` is at least 2**128, then the highest bit of `x` is at least 128.\n        // solhint-disable no-inline-assembly\n        assembly {\n            // `f` is set to 1\u003c\u003c7 if `x \u003e= 2**128` and to 0 otherwise.\n            let f := shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\n            // If `x \u003e= 2**128` then set `msb` highest bit to 1 and shift `x` right by 128.\n            // Otherwise, `msb` remains 0 and `x` remains unchanged.\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        // `x` is now at most 2**128 - 1. Continue the same way, the next highest bit is 1\u003c\u003c6 == 64.\n        assembly {\n            // `f` is set to 1\u003c\u003c6 if `x \u003e= 2**64` and to 0 otherwise.\n            let f := shl(6, gt(x, 0xFFFFFFFFFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c5 if `x \u003e= 2**32` and to 0 otherwise.\n            let f := shl(5, gt(x, 0xFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c4 if `x \u003e= 2**16` and to 0 otherwise.\n            let f := shl(4, gt(x, 0xFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c3 if `x \u003e= 2**8` and to 0 otherwise.\n            let f := shl(3, gt(x, 0xFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c2 if `x \u003e= 2**4` and to 0 otherwise.\n            let f := shl(2, gt(x, 0xF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c1 if `x \u003e= 2**2` and to 0 otherwise.\n            let f := shl(1, gt(x, 0x3))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1 if `x \u003e= 2**1` and to 0 otherwise.\n            let f := gt(x, 0x1)\n            msb := or(msb, f)\n        }\n    }\n\n    /// @dev Wraps (mantissa, exponent) pair into Number.\n    function _encode(uint8 mantissa, uint8 exponent) private pure returns (Number) {\n        // Casts below are upcasts, so they are safe.\n        return Number.wrap(uint16(mantissa) \u003c\u003c SHIFT_MANTISSA | uint16(exponent));\n    }\n}\n\n// contracts/libs/stack/Request.sol\n\n/// Request is encoded data with \"message execution request\".\ntype Request is uint192;\n\nusing RequestLib for Request global;\n\n/// Library for formatting _the request part_ of _the base messages_.\n/// - Request represents a message sender requirements for the message execution on the destination chain.\n/// - Request occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n/// \u003e gasDrop field is included for future compatibility and is ignored at the moment.\n///\n/// # Request stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type   | Bytes | Description                                          |\n/// | ---------- | -------- | ------ | ----- | ---------------------------------------------------- |\n/// | (024..012] | gasDrop  | uint96 | 12    | Minimum amount of gas token to drop to the recipient |\n/// | (012..004] | gasLimit | uint64 | 8     | Minimum amount of gas units to supply for execution  |\n/// | (004..000] | version  | uint32 | 4     | Base message version to pass to the recipient        |\n\nlibrary RequestLib {\n    /// @dev Amount of bits to shift to gasDrop field\n    uint192 private constant SHIFT_GAS_DROP = 12 * 8;\n    /// @dev Amount of bits to shift to gasLimit field\n    uint192 private constant SHIFT_GAS_LIMIT = 4 * 8;\n\n    /// @notice Returns an encoded request with the given fields\n    /// @param gasDrop_     Minimum amount of gas token to drop to the recipient (ignored at the moment)\n    /// @param gasLimit_    Minimum amount of gas units to supply for execution\n    /// @param version_     Base message version to pass to the recipient\n    function encodeRequest(uint96 gasDrop_, uint64 gasLimit_, uint32 version_) internal pure returns (Request) {\n        // Casts below are upcasts, so they are safe\n        return Request.wrap(uint192(gasDrop_) \u003c\u003c SHIFT_GAS_DROP | uint192(gasLimit_) \u003c\u003c SHIFT_GAS_LIMIT | version_);\n    }\n\n    /// @notice Wraps the padded encoded request into a Request-typed value.\n    /// @dev The \"padded\" request is simply an encoded request casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded requests\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedRequest) internal pure returns (Request) {\n        // Casting to uint192 will truncate the highest bits, which is the behavior we want\n        return Request.wrap(uint192(paddedRequest));\n    }\n\n    /// @notice Returns the requested of gas token to drop to the recipient.\n    function gasDrop(Request request) internal pure returns (uint96) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return uint96(Request.unwrap(request) \u003e\u003e SHIFT_GAS_DROP);\n    }\n\n    /// @notice Returns the requested minimum amount of gas units to supply for execution.\n    function gasLimit(Request request) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Request.unwrap(request) \u003e\u003e SHIFT_GAS_LIMIT);\n    }\n\n    /// @notice Returns the requested base message version to pass to the recipient.\n    function version(Request request) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Request.unwrap(request));\n    }\n}\n\n// node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        require(value \u003c= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        require(value \u003c= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        require(value \u003c= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value \u003c= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        require(value \u003c= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        require(value \u003c= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        require(value \u003c= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        require(value \u003c= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        require(value \u003c= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        require(value \u003c= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        require(value \u003c= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        require(value \u003c= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        require(value \u003c= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        require(value \u003c= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        require(value \u003c= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value \u003c= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        require(value \u003c= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        require(value \u003c= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        require(value \u003c= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value \u003c= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        require(value \u003c= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        require(value \u003c= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        require(value \u003c= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value \u003c= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        require(value \u003c= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        require(value \u003c= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        require(value \u003c= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value \u003c= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        require(value \u003c= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value \u003c= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value \u003c= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     *\n     * _Available since v3.0._\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value \u003e= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     *\n     * _Available since v3.0._\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value \u003c= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     *\n     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length \u003e 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance \u003e= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance \u003e= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length \u003e 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n\n// contracts/base/MultiCallable.sol\n\n/// @notice Collection of Multicall utilities. Fork of Multicall3:\n/// https://github.com/mds1/multicall/blob/master/src/Multicall3.sol\nabstract contract MultiCallable {\n    struct Call {\n        bool allowFailure;\n        bytes callData;\n    }\n\n    struct Result {\n        bool success;\n        bytes returnData;\n    }\n\n    /// @notice Aggregates a few calls to this contract into one multicall without modifying `msg.sender`.\n    function multicall(Call[] calldata calls) external returns (Result[] memory callResults) {\n        uint256 amount = calls.length;\n        callResults = new Result[](amount);\n        Call calldata call_;\n        for (uint256 i = 0; i \u003c amount;) {\n            call_ = calls[i];\n            Result memory result = callResults[i];\n            // We perform a delegate call to ourselves here. Delegate call does not modify `msg.sender`, so\n            // this will have the same effect as if `msg.sender` performed all the calls themselves one by one.\n            // solhint-disable-next-line avoid-low-level-calls\n            (result.success, result.returnData) = address(this).delegatecall(call_.callData);\n            // solhint-disable-next-line no-inline-assembly\n            assembly {\n                // Revert if the call fails and failure is not allowed\n                // `allowFailure := calldataload(call_)` and `success := mload(result)`\n                if iszero(or(calldataload(call_), mload(result))) {\n                    // Revert with `0x4d6a2328` (function selector for `MulticallFailed()`)\n                    mstore(0x00, 0x4d6a232800000000000000000000000000000000000000000000000000000000)\n                    revert(0x00, 0x04)\n                }\n            }\n            unchecked {\n                ++i;\n            }\n        }\n    }\n}\n\n// contracts/base/Version.sol\n\n/**\n * @title Versioned\n * @notice Version getter for contracts. Doesn't use any storage slots, meaning\n * it will never cause any troubles with the upgradeable contracts. For instance, this contract\n * can be added or removed from the inheritance chain without shifting the storage layout.\n */\nabstract contract Versioned {\n    /**\n     * @notice Struct that is mimicking the storage layout of a string with 32 bytes or less.\n     * Length is limited by 32, so the whole string payload takes two memory words:\n     * @param length    String length\n     * @param data      String characters\n     */\n    struct _ShortString {\n        uint256 length;\n        bytes32 data;\n    }\n\n    /// @dev Length of the \"version string\"\n    uint256 private immutable _length;\n    /// @dev Bytes representation of the \"version string\".\n    /// Strings with length over 32 are not supported!\n    bytes32 private immutable _data;\n\n    constructor(string memory version_) {\n        _length = bytes(version_).length;\n        if (_length \u003e 32) revert IncorrectVersionLength();\n        // bytes32 is left-aligned =\u003e this will store the byte representation of the string\n        // with the trailing zeroes to complete the 32-byte word\n        _data = bytes32(bytes(version_));\n    }\n\n    function version() external view returns (string memory versionString) {\n        // Load the immutable values to form the version string\n        _ShortString memory str = _ShortString(_length, _data);\n        // The only way to do this cast is doing some dirty assembly\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            versionString := str\n        }\n    }\n}\n\n// contracts/libs/ChainContext.sol\n\n/// @notice Library for accessing chain context variables as tightly packed integers.\n/// Messaging contracts should rely on this library for accessing chain context variables\n/// instead of doing the casting themselves.\nlibrary ChainContext {\n    using SafeCast for uint256;\n\n    /// @notice Returns the current block number as uint40.\n    /// @dev Reverts if block number is greater than 40 bits, which is not supposed to happen\n    /// until the block.timestamp overflows (assuming block time is at least 1 second).\n    function blockNumber() internal view returns (uint40) {\n        return block.number.toUint40();\n    }\n\n    /// @notice Returns the current block timestamp as uint40.\n    /// @dev Reverts if block timestamp is greater than 40 bits, which is\n    /// supposed to happen approximately in year 36835.\n    function blockTimestamp() internal view returns (uint40) {\n        return block.timestamp.toUint40();\n    }\n\n    /// @notice Returns the chain id as uint32.\n    /// @dev Reverts if chain id is greater than 32 bits, which is not\n    /// supposed to happen in production.\n    function chainId() internal view returns (uint32) {\n        return block.chainid.toUint32();\n    }\n}\n\n// contracts/libs/Structures.sol\n\n// Here we define common enums and structures to enable their easier reusing later.\n\n// ═══════════════════════════════ AGENT STATUS ════════════════════════════════\n\n/// @dev Potential statuses for the off-chain bonded agent:\n/// - Unknown: never provided a bond =\u003e signature not valid\n/// - Active: has a bond in BondingManager =\u003e signature valid\n/// - Unstaking: has a bond in BondingManager, initiated the unstaking =\u003e signature not valid\n/// - Resting: used to have a bond in BondingManager, successfully unstaked =\u003e signature not valid\n/// - Fraudulent: proven to commit fraud, value in Merkle Tree not updated =\u003e signature not valid\n/// - Slashed: proven to commit fraud, value in Merkle Tree was updated =\u003e signature not valid\n/// Unstaked agent could later be added back to THE SAME domain by staking a bond again.\n/// Honest agent: Unknown -\u003e Active -\u003e unstaking -\u003e Resting -\u003e Active ...\n/// Malicious agent: Unknown -\u003e Active -\u003e Fraudulent -\u003e Slashed\n/// Malicious agent: Unknown -\u003e Active -\u003e Unstaking -\u003e Fraudulent -\u003e Slashed\nenum AgentFlag {\n    Unknown,\n    Active,\n    Unstaking,\n    Resting,\n    Fraudulent,\n    Slashed\n}\n\n/// @notice Struct for storing an agent in the BondingManager contract.\nstruct AgentStatus {\n    AgentFlag flag;\n    uint32 domain;\n    uint32 index;\n}\n// 184 bits available for tight packing\n\nusing StructureUtils for AgentStatus global;\n\n/// @notice Potential statuses of an agent in terms of being in dispute\n/// - None: agent is not in dispute\n/// - Pending: agent is in unresolved dispute\n/// - Slashed: agent was in dispute that lead to agent being slashed\n/// Note: agent who won the dispute has their status reset to None\nenum DisputeFlag {\n    None,\n    Pending,\n    Slashed\n}\n\n/// @notice Struct for storing dispute status of an agent.\n/// @param flag         Dispute flag: None/Pending/Slashed.\n/// @param openedAt     Timestamp when the latest agent dispute was opened (zero if not opened).\n/// @param resolvedAt   Timestamp when the latest agent dispute was resolved (zero if not resolved).\nstruct DisputeStatus {\n    DisputeFlag flag;\n    uint40 openedAt;\n    uint40 resolvedAt;\n}\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\n/// @notice Struct representing the status of Destination contract.\n/// @param snapRootTime     Timestamp when latest snapshot root was accepted\n/// @param agentRootTime    Timestamp when latest agent root was accepted\n/// @param notaryIndex      Index of Notary who signed the latest agent root\nstruct DestinationStatus {\n    uint40 snapRootTime;\n    uint40 agentRootTime;\n    uint32 notaryIndex;\n}\n\n// ═══════════════════════════════ EXECUTION HUB ═══════════════════════════════\n\n/// @notice Potential statuses of the message in Execution Hub.\n/// - None: there hasn't been a valid attempt to execute the message yet\n/// - Failed: there was a valid attempt to execute the message, but recipient reverted\n/// - Success: there was a valid attempt to execute the message, and recipient did not revert\n/// Note: message can be executed until its status is Success\nenum MessageStatus {\n    None,\n    Failed,\n    Success\n}\n\nlibrary StructureUtils {\n    /// @notice Checks that Agent is Active\n    function verifyActive(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active) {\n            revert AgentNotActive();\n        }\n    }\n\n    /// @notice Checks that Agent is Unstaking\n    function verifyUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Unstaking) {\n            revert AgentNotUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Active or Unstaking\n    function verifyActiveUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active \u0026\u0026 status.flag != AgentFlag.Unstaking) {\n            revert AgentNotActiveNorUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Fraudulent\n    function verifyFraudulent(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Fraudulent) {\n            revert AgentNotFraudulent();\n        }\n    }\n\n    /// @notice Checks that Agent is not Unknown\n    function verifyKnown(AgentStatus memory status) internal pure {\n        if (status.flag == AgentFlag.Unknown) {\n            revert AgentUnknown();\n        }\n    }\n}\n\n// contracts/libs/memory/MemView.sol\n\n/// @dev MemView is an untyped view over a portion of memory to be used instead of `bytes memory`\ntype MemView is uint256;\n\n/// @dev Attach library functions to MemView\nusing MemViewLib for MemView global;\n\n/// @notice Library for operations with the memory views.\n/// Forked from https://github.com/summa-tx/memview-sol with several breaking changes:\n/// - The codebase is ported to Solidity 0.8\n/// - Custom errors are added\n/// - The runtime type checking is replaced with compile-time check provided by User-Defined Value Types\n///   https://docs.soliditylang.org/en/latest/types.html#user-defined-value-types\n/// - uint256 is used as the underlying type for the \"memory view\" instead of bytes29.\n///   It is wrapped into MemView custom type in order not to be confused with actual integers.\n/// - Therefore the \"type\" field is discarded, allowing to allocate 16 bytes for both view location and length\n/// - The documentation is expanded\n/// - Library functions unused by the rest of the codebase are removed\n//  - Very pretty code separators are added :)\nlibrary MemViewLib {\n    /// @notice Stack layout for uint256 (from highest bits to lowest)\n    /// (32 .. 16]      loc     16 bytes    Memory address of underlying bytes\n    /// (16 .. 00]      len     16 bytes    Length of underlying bytes\n\n    // ═══════════════════════════════════════════ BUILDING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Instantiate a new untyped memory view. This should generally not be called directly.\n     * Prefer `ref` wherever possible.\n     * @param loc_          The memory address\n     * @param len_          The length\n     * @return The new view with the specified location and length\n     */\n    function build(uint256 loc_, uint256 len_) internal pure returns (MemView) {\n        uint256 end_ = loc_ + len_;\n        // Make sure that a view is not constructed that points to unallocated memory\n        // as this could be indicative of a buffer overflow attack\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            if gt(end_, mload(0x40)) { end_ := 0 }\n        }\n        if (end_ == 0) {\n            revert UnallocatedMemory();\n        }\n        return _unsafeBuildUnchecked(loc_, len_);\n    }\n\n    /**\n     * @notice Instantiate a memory view from a byte array.\n     * @dev Note that due to Solidity memory representation, it is not possible to\n     * implement a deref, as the `bytes` type stores its len in memory.\n     * @param arr           The byte array\n     * @return The memory view over the provided byte array\n     */\n    function ref(bytes memory arr) internal pure returns (MemView) {\n        uint256 len_ = arr.length;\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 loc_;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // We add 0x20, so that the view starts exactly where the array data starts\n            loc_ := add(arr, 0x20)\n        }\n        return build(loc_, len_);\n    }\n\n    // ════════════════════════════════════════════ CLONING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to the new memory.\n     * @param memView       The memory view\n     * @return arr          The cloned byte array\n     */\n    function clone(MemView memView) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        unchecked {\n            _unsafeCopyTo(memView, ptr + 0x20);\n        }\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 len_ = memView.len();\n        uint256 footprint_ = memView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    /**\n     * @notice Copies all views, joins them into a new bytearray.\n     * @param memViews      The memory views\n     * @return arr          The new byte array with joined data behind the given views\n     */\n    function join(MemView[] memory memViews) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        MemView newView;\n        unchecked {\n            newView = _unsafeJoin(memViews, ptr + 0x20);\n        }\n        uint256 len_ = newView.len();\n        uint256 footprint_ = newView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    // ══════════════════════════════════════════ INSPECTING MEMORY VIEW ═══════════════════════════════════════════════\n\n    /**\n     * @notice Returns the memory address of the underlying bytes.\n     * @param memView       The memory view\n     * @return loc_         The memory address\n     */\n    function loc(MemView memView) internal pure returns (uint256 loc_) {\n        // loc is stored in the highest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u003e\u003e 128;\n    }\n\n    /**\n     * @notice Returns the number of bytes of the view.\n     * @param memView       The memory view\n     * @return len_         The length of the view\n     */\n    function len(MemView memView) internal pure returns (uint256 len_) {\n        // len is stored in the lowest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u0026 type(uint128).max;\n    }\n\n    /**\n     * @notice Returns the endpoint of `memView`.\n     * @param memView       The memory view\n     * @return end_         The endpoint of `memView`\n     */\n    function end(MemView memView) internal pure returns (uint256 end_) {\n        // The endpoint never overflows uint128, let alone uint256, so we could use unchecked math here\n        unchecked {\n            return memView.loc() + memView.len();\n        }\n    }\n\n    /**\n     * @notice Returns the number of memory words this memory view occupies, rounded up.\n     * @param memView       The memory view\n     * @return words_       The number of memory words\n     */\n    function words(MemView memView) internal pure returns (uint256 words_) {\n        // returning ceil(length / 32.0)\n        unchecked {\n            return (memView.len() + 31) \u003e\u003e 5;\n        }\n    }\n\n    /**\n     * @notice Returns the in-memory footprint of a fresh copy of the view.\n     * @param memView       The memory view\n     * @return footprint_   The in-memory footprint of a fresh copy of the view.\n     */\n    function footprint(MemView memView) internal pure returns (uint256 footprint_) {\n        // words() * 32\n        return memView.words() \u003c\u003c 5;\n    }\n\n    // ════════════════════════════════════════════ HASHING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the keccak256 hash of the underlying memory\n     * @param memView       The memory view\n     * @return digest       The keccak256 hash of the underlying memory\n     */\n    function keccak(MemView memView) internal pure returns (bytes32 digest) {\n        uint256 loc_ = memView.loc();\n        uint256 len_ = memView.len();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            digest := keccak256(loc_, len_)\n        }\n    }\n\n    /**\n     * @notice Adds a salt to the keccak256 hash of the underlying data and returns the keccak256 hash of the\n     * resulting data.\n     * @param memView       The memory view\n     * @return digestSalted keccak256(salt, keccak256(memView))\n     */\n    function keccakSalted(MemView memView, bytes32 salt) internal pure returns (bytes32 digestSalted) {\n        return keccak256(bytes.concat(salt, memView.keccak()));\n    }\n\n    // ════════════════════════════════════════════ SLICING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Safe slicing without memory modification.\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the given index\n     */\n    function slice(MemView memView, uint256 index_, uint256 len_) internal pure returns (MemView) {\n        uint256 loc_ = memView.loc();\n        // Ensure it doesn't overrun the view\n        if (loc_ + index_ + len_ \u003e memView.end()) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // loc_ + index_ \u003c= memView.end()\n            return build({loc_: loc_ + index_, len_: len_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing bytes from `index` to end(memView).\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @return The new view for the slice starting from the given index until the initial view endpoint\n     */\n    function sliceFrom(MemView memView, uint256 index_) internal pure returns (MemView) {\n        uint256 len_ = memView.len();\n        // Ensure it doesn't overrun the view\n        if (index_ \u003e len_) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // index_ \u003c= len_ =\u003e memView.loc() + index_ \u003c= memView.loc() + memView.len() == memView.end()\n            return build({loc_: memView.loc() + index_, len_: len_ - index_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the first `len` bytes.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the initial view beginning\n     */\n    function prefix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        return memView.slice({index_: 0, len_: len_});\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the last `len` byte.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length until the initial view endpoint\n     */\n    function postfix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        uint256 viewLen = memView.len();\n        // Ensure it doesn't overrun the view\n        if (len_ \u003e viewLen) {\n            revert ViewOverrun();\n        }\n        // Could do the unchecked math due to the check above\n        uint256 index_;\n        unchecked {\n            index_ = viewLen - len_;\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // len_ \u003c= memView.len() =\u003e memView.loc() \u003c= loc_ \u003c= memView.end()\n            return build({loc_: memView.loc() + viewLen - len_, len_: len_});\n        }\n    }\n\n    // ═══════════════════════════════════════════ INDEXING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Load up to 32 bytes from the view onto the stack.\n     * @dev Returns a bytes32 with only the `bytes_` HIGHEST bytes set.\n     * This can be immediately cast to a smaller fixed-length byte array.\n     * To automatically cast to an integer, use `indexUint`.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return result       The 32 byte result having only `bytes_` highest bytes set\n     */\n    function index(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (bytes32 result) {\n        if (bytes_ == 0) {\n            return bytes32(0);\n        }\n        // Can't load more than 32 bytes to the stack in one go\n        if (bytes_ \u003e 32) {\n            revert IndexedTooMuch();\n        }\n        // The last indexed byte should be within view boundaries\n        if (index_ + bytes_ \u003e memView.len()) {\n            revert ViewOverrun();\n        }\n        uint256 bitLength = bytes_ \u003c\u003c 3; // bytes_ * 8\n        uint256 loc_ = memView.loc();\n        // Get a mask with `bitLength` highest bits set\n        uint256 mask;\n        // 0x800...00 binary representation is 100...00\n        // sar stands for \"signed arithmetic shift\": https://en.wikipedia.org/wiki/Arithmetic_shift\n        // sar(N-1, 100...00) = 11...100..00, with exactly N highest bits set to 1\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            mask := sar(sub(bitLength, 1), 0x8000000000000000000000000000000000000000000000000000000000000000)\n        }\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load a full word using index offset, and apply mask to ignore non-relevant bytes\n            result := and(mload(add(loc_, index_)), mask)\n        }\n    }\n\n    /**\n     * @notice Parse an unsigned integer from the view at `index`.\n     * @dev Requires that the view have \u003e= `bytes_` bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return The unsigned integer\n     */\n    function indexUint(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (uint256) {\n        bytes32 indexedBytes = memView.index(index_, bytes_);\n        // `index()` returns left-aligned `bytes_`, while integers are right-aligned\n        // Shifting here to right-align with the full 32 bytes word: need to shift right `(32 - bytes_)` bytes\n        unchecked {\n            // memView.index() reverts when bytes_ \u003e 32, thus unchecked math\n            return uint256(indexedBytes) \u003e\u003e ((32 - bytes_) \u003c\u003c 3);\n        }\n    }\n\n    /**\n     * @notice Parse an address from the view at `index`.\n     * @dev Requires that the view have \u003e= 20 bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @return The address\n     */\n    function indexAddress(MemView memView, uint256 index_) internal pure returns (address) {\n        // index 20 bytes as `uint160`, and then cast to `address`\n        return address(uint160(memView.indexUint(index_, 20)));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns a memory view over the specified memory location\n    /// without checking if it points to unallocated memory.\n    function _unsafeBuildUnchecked(uint256 loc_, uint256 len_) private pure returns (MemView) {\n        // There is no scenario where loc or len would overflow uint128, so we omit this check.\n        // We use the highest 128 bits to encode the location and the lowest 128 bits to encode the length.\n        return MemView.wrap((loc_ \u003c\u003c 128) | len_);\n    }\n\n    /**\n     * @notice Copy the view to a location, return an unsafe memory reference\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memView       The memory view\n     * @param newLoc        The new location to copy the underlying view data\n     * @return The memory view over the unsafe memory with the copied underlying data\n     */\n    function _unsafeCopyTo(MemView memView, uint256 newLoc) private view returns (MemView) {\n        uint256 len_ = memView.len();\n        uint256 oldLoc = memView.loc();\n\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (newLoc \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        bool res;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // use the identity precompile (0x04) to copy\n            res := staticcall(gas(), 0x04, oldLoc, len_, newLoc, len_)\n        }\n        if (!res) revert PrecompileOutOfGas();\n        return _unsafeBuildUnchecked({loc_: newLoc, len_: len_});\n    }\n\n    /**\n     * @notice Join the views in memory, return an unsafe reference to the memory.\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memViews      The memory views\n     * @return The conjoined view pointing to the new memory\n     */\n    function _unsafeJoin(MemView[] memory memViews, uint256 location) private view returns (MemView) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (location \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        // Copy the views to the specified location one by one, by tracking the amount of copied bytes so far\n        uint256 offset = 0;\n        for (uint256 i = 0; i \u003c memViews.length;) {\n            MemView memView = memViews[i];\n            // We can use the unchecked math here as location + sum(view.length) will never overflow uint256\n            unchecked {\n                _unsafeCopyTo(memView, location + offset);\n                offset += memView.len();\n                ++i;\n            }\n        }\n        return _unsafeBuildUnchecked({loc_: location, len_: offset});\n    }\n}\n\n// contracts/libs/merkle/MerkleMath.sol\n\nlibrary MerkleMath {\n    // ═════════════════════════════════════════ BASIC MERKLE CALCULATIONS ═════════════════════════════════════════════\n\n    /**\n     * @notice Calculates the merkle root for the given leaf and merkle proof.\n     * @dev Will revert if proof length exceeds the tree height.\n     * @param index     Index of `leaf` in tree\n     * @param leaf      Leaf of the merkle tree\n     * @param proof     Proof of inclusion of `leaf` in the tree\n     * @param height    Height of the merkle tree\n     * @return root_    Calculated Merkle Root\n     */\n    function proofRoot(uint256 index, bytes32 leaf, bytes32[] memory proof, uint256 height)\n        internal\n        pure\n        returns (bytes32 root_)\n    {\n        // Proof length could not exceed the tree height\n        uint256 proofLen = proof.length;\n        if (proofLen \u003e height) revert TreeHeightTooLow();\n        root_ = leaf;\n        /// @dev Apply unchecked to all ++h operations\n        unchecked {\n            // Go up the tree levels from the leaf following the proof\n            for (uint256 h = 0; h \u003c proofLen; ++h) {\n                // Get a sibling node on current level: this is proof[h]\n                root_ = getParent(root_, proof[h], index, h);\n            }\n            // Go up to the root: the remaining siblings are EMPTY\n            for (uint256 h = proofLen; h \u003c height; ++h) {\n                root_ = getParent(root_, bytes32(0), index, h);\n            }\n        }\n    }\n\n    /**\n     * @notice Calculates the parent of a node on the path from one of the leafs to root.\n     * @param node          Node on a path from tree leaf to root\n     * @param sibling       Sibling for a given node\n     * @param leafIndex     Index of the tree leaf\n     * @param nodeHeight    \"Level height\" for `node` (ZERO for leafs, ORIGIN_TREE_HEIGHT for root)\n     */\n    function getParent(bytes32 node, bytes32 sibling, uint256 leafIndex, uint256 nodeHeight)\n        internal\n        pure\n        returns (bytes32 parent)\n    {\n        // Index for `node` on its \"tree level\" is (leafIndex / 2**height)\n        // \"Left child\" has even index, \"right child\" has odd index\n        if ((leafIndex \u003e\u003e nodeHeight) \u0026 1 == 0) {\n            // Left child\n            return getParent(node, sibling);\n        } else {\n            // Right child\n            return getParent(sibling, node);\n        }\n    }\n\n    /// @notice Calculates the parent of tow nodes in the merkle tree.\n    /// @dev We use implementation with H(0,0) = 0\n    /// This makes EVERY empty node in the tree equal to ZERO,\n    /// saving us from storing H(0,0), H(H(0,0), H(0, 0)), and so on\n    /// @param leftChild    Left child of the calculated node\n    /// @param rightChild   Right child of the calculated node\n    /// @return parent      Value for the node having above mentioned children\n    function getParent(bytes32 leftChild, bytes32 rightChild) internal pure returns (bytes32 parent) {\n        if (leftChild == bytes32(0) \u0026\u0026 rightChild == bytes32(0)) {\n            return 0;\n        } else {\n            return keccak256(bytes.concat(leftChild, rightChild));\n        }\n    }\n\n    // ════════════════════════════════ ROOT/PROOF CALCULATION FOR A LIST OF LEAFS ═════════════════════════════════════\n\n    /**\n     * @notice Calculates merkle root for a list of given leafs.\n     * Merkle Tree is constructed by padding the list with ZERO values for leafs until list length is `2**height`.\n     * Merkle Root is calculated for the constructed tree, and then saved in `leafs[0]`.\n     * \u003e Note:\n     * \u003e - `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * \u003e - Caller is expected not to reuse `hashes` list after the call, and only use `leafs[0]` value,\n     * which is guaranteed to contain the calculated merkle root.\n     * \u003e - root is calculated using the `H(0,0) = 0` Merkle Tree implementation. See MerkleTree.sol for details.\n     * @dev Amount of leaves should be at most `2**height`\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param height    Height of the Merkle Tree to construct\n     */\n    function calculateRoot(bytes32[] memory hashes, uint256 height) internal pure {\n        uint256 levelLength = hashes.length;\n        // Amount of hashes could not exceed amount of leafs in tree with the given height\n        if (levelLength \u003e (1 \u003c\u003c height)) revert TreeHeightTooLow();\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\": the amount of iterations for the for loop above.\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n            }\n        }\n    }\n\n    /**\n     * @notice Generates a proof of inclusion of a leaf in the list. If the requested index is outside\n     * of the list range, generates a proof of inclusion for an empty leaf (proof of non-inclusion).\n     * The Merkle Tree is constructed by padding the list with ZERO values until list length is a power of two\n     * __AND__ index is in the extended list range. For example:\n     *  - `hashes.length == 6` and `0 \u003c= index \u003c= 7` will \"extend\" the list to 8 entries.\n     *  - `hashes.length == 6` and `7 \u003c index \u003c= 15` will \"extend\" the list to 16 entries.\n     * \u003e Note: `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * Caller is expected not to reuse `hashes` list after the call.\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param index     Leaf index to generate the proof for\n     * @return proof    Generated merkle proof\n     */\n    function calculateProof(bytes32[] memory hashes, uint256 index) internal pure returns (bytes32[] memory proof) {\n        // Use only meaningful values for the shortened proof\n        // Check if index is within the list range (we want to generates proofs for outside leafs as well)\n        uint256 height = getHeight(index \u003c hashes.length ? hashes.length : (index + 1));\n        proof = new bytes32[](height);\n        uint256 levelLength = hashes.length;\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Use sibling for the merkle proof; `index^1` is index of our sibling\n                proof[h] = (index ^ 1 \u003c levelLength) ? hashes[index ^ 1] : bytes32(0);\n\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\"\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n                // Traverse to parent node\n                index \u003e\u003e= 1;\n            }\n        }\n    }\n\n    /// @notice Returns the height of the tree having a given amount of leafs.\n    function getHeight(uint256 leafs) internal pure returns (uint256 height) {\n        uint256 amount = 1;\n        while (amount \u003c leafs) {\n            unchecked {\n                ++height;\n            }\n            amount \u003c\u003c= 1;\n        }\n    }\n}\n\n// contracts/libs/stack/GasData.sol\n\n/// GasData in encoded data with \"basic information about gas prices\" for some chain.\ntype GasData is uint96;\n\nusing GasDataLib for GasData global;\n\n/// ChainGas is encoded data with given chain's \"basic information about gas prices\".\ntype ChainGas is uint128;\n\nusing GasDataLib for ChainGas global;\n\n/// Library for encoding and decoding GasData and ChainGas structs.\n/// # GasData\n/// `GasData` is a struct to store the \"basic information about gas prices\", that could\n/// be later used to approximate the cost of a message execution, and thus derive the\n/// minimal tip values for sending a message to the chain.\n/// \u003e - `GasData` is supposed to be cached by `GasOracle` contract, allowing to store the\n/// \u003e approximates instead of the exact values, and thus save on storage costs.\n/// \u003e - For instance, if `GasOracle` only updates the values on +- 10% change, having an\n/// \u003e 0.4% error on the approximates would be acceptable.\n/// `GasData` is supposed to be included in the Origin's state, which are synced across\n/// chains using Agent-signed snapshots and attestations.\n/// ## GasData stack layout (from highest bits to lowest)\n///\n/// | Position   | Field        | Type   | Bytes | Description                                         |\n/// | ---------- | ------------ | ------ | ----- | --------------------------------------------------- |\n/// | (012..010] | gasPrice     | uint16 | 2     | Gas price for the chain (in Wei per gas unit)       |\n/// | (010..008] | dataPrice    | uint16 | 2     | Calldata price (in Wei per byte of content)         |\n/// | (008..006] | execBuffer   | uint16 | 2     | Tx fee safety buffer for message execution (in Wei) |\n/// | (006..004] | amortAttCost | uint16 | 2     | Amortized cost for attestation submission (in Wei)  |\n/// | (004..002] | etherPrice   | uint16 | 2     | Chain's Ether Price / Mainnet Ether Price (in BWAD) |\n/// | (002..000] | markup       | uint16 | 2     | Markup for the message execution (in BWAD)          |\n/// \u003e See Number.sol for more details on `Number` type and BWAD (binary WAD) math.\n///\n/// ## ChainGas stack layout (from highest bits to lowest)\n///\n/// | Position   | Field   | Type   | Bytes | Description      |\n/// | ---------- | ------- | ------ | ----- | ---------------- |\n/// | (016..004] | gasData | uint96 | 12    | Chain's gas data |\n/// | (004..000] | domain  | uint32 | 4     | Chain's domain   |\nlibrary GasDataLib {\n    /// @dev Amount of bits to shift to gasPrice field\n    uint96 private constant SHIFT_GAS_PRICE = 10 * 8;\n    /// @dev Amount of bits to shift to dataPrice field\n    uint96 private constant SHIFT_DATA_PRICE = 8 * 8;\n    /// @dev Amount of bits to shift to execBuffer field\n    uint96 private constant SHIFT_EXEC_BUFFER = 6 * 8;\n    /// @dev Amount of bits to shift to amortAttCost field\n    uint96 private constant SHIFT_AMORT_ATT_COST = 4 * 8;\n    /// @dev Amount of bits to shift to etherPrice field\n    uint96 private constant SHIFT_ETHER_PRICE = 2 * 8;\n\n    /// @dev Amount of bits to shift to gasData field\n    uint128 private constant SHIFT_GAS_DATA = 4 * 8;\n\n    // ═════════════════════════════════════════════════ GAS DATA ══════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded GasData struct with the given fields.\n    /// @param gasPrice_        Gas price for the chain (in Wei per gas unit)\n    /// @param dataPrice_       Calldata price (in Wei per byte of content)\n    /// @param execBuffer_      Tx fee safety buffer for message execution (in Wei)\n    /// @param amortAttCost_    Amortized cost for attestation submission (in Wei)\n    /// @param etherPrice_      Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n    /// @param markup_          Markup for the message execution (in BWAD)\n    function encodeGasData(\n        Number gasPrice_,\n        Number dataPrice_,\n        Number execBuffer_,\n        Number amortAttCost_,\n        Number etherPrice_,\n        Number markup_\n    ) internal pure returns (GasData) {\n        // Number type wraps uint16, so could safely be casted to uint96\n        // forgefmt: disable-next-item\n        return GasData.wrap(\n            uint96(Number.unwrap(gasPrice_)) \u003c\u003c SHIFT_GAS_PRICE |\n            uint96(Number.unwrap(dataPrice_)) \u003c\u003c SHIFT_DATA_PRICE |\n            uint96(Number.unwrap(execBuffer_)) \u003c\u003c SHIFT_EXEC_BUFFER |\n            uint96(Number.unwrap(amortAttCost_)) \u003c\u003c SHIFT_AMORT_ATT_COST |\n            uint96(Number.unwrap(etherPrice_)) \u003c\u003c SHIFT_ETHER_PRICE |\n            uint96(Number.unwrap(markup_))\n        );\n    }\n\n    /// @notice Wraps padded uint256 value into GasData struct.\n    function wrapGasData(uint256 paddedGasData) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(paddedGasData));\n    }\n\n    /// @notice Returns the gas price, in Wei per gas unit.\n    function gasPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_GAS_PRICE));\n    }\n\n    /// @notice Returns the calldata price, in Wei per byte of content.\n    function dataPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_DATA_PRICE));\n    }\n\n    /// @notice Returns the tx fee safety buffer for message execution, in Wei.\n    function execBuffer(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_EXEC_BUFFER));\n    }\n\n    /// @notice Returns the amortized cost for attestation submission, in Wei.\n    function amortAttCost(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_AMORT_ATT_COST));\n    }\n\n    /// @notice Returns the ratio of Chain's Ether Price / Mainnet Ether Price, in BWAD math.\n    function etherPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_ETHER_PRICE));\n    }\n\n    /// @notice Returns the markup for the message execution, in BWAD math.\n    function markup(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data)));\n    }\n\n    // ════════════════════════════════════════════════ CHAIN DATA ═════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded ChainGas struct with the given fields.\n    /// @param gasData_ Chain's gas data\n    /// @param domain_  Chain's domain\n    function encodeChainGas(GasData gasData_, uint32 domain_) internal pure returns (ChainGas) {\n        // GasData type wraps uint96, so could safely be casted to uint128\n        return ChainGas.wrap(uint128(GasData.unwrap(gasData_)) \u003c\u003c SHIFT_GAS_DATA | uint128(domain_));\n    }\n\n    /// @notice Wraps padded uint256 value into ChainGas struct.\n    function wrapChainGas(uint256 paddedChainGas) internal pure returns (ChainGas) {\n        // Casting to uint128 will truncate the highest bits, which is the behavior we want\n        return ChainGas.wrap(uint128(paddedChainGas));\n    }\n\n    /// @notice Returns the chain's gas data.\n    function gasData(ChainGas data) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(ChainGas.unwrap(data) \u003e\u003e SHIFT_GAS_DATA));\n    }\n\n    /// @notice Returns the chain's domain.\n    function domain(ChainGas data) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(ChainGas.unwrap(data));\n    }\n\n    /// @notice Returns the hash for the list of ChainGas structs.\n    function snapGasHash(ChainGas[] memory snapGas) internal pure returns (bytes32 snapGasHash_) {\n        // Use assembly to calculate the hash of the array without copying it\n        // ChainGas takes a single word of storage, thus ChainGas[] is stored in the following way:\n        // 0x00: length of the array, in words\n        // 0x20: first ChainGas struct\n        // 0x40: second ChainGas struct\n        // And so on...\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Find the location where the array data starts, we add 0x20 to skip the length field\n            let loc := add(snapGas, 0x20)\n            // Load the length of the array (in words).\n            // Shifting left 5 bits is equivalent to multiplying by 32: this converts from words to bytes.\n            let len := shl(5, mload(snapGas))\n            // Calculate the hash of the array\n            snapGasHash_ := keccak256(loc, len)\n        }\n    }\n}\n\n// contracts/libs/stack/Header.sol\n\n/// Header is encoded data with \"general routing information\".\ntype Header is uint136;\n\nusing HeaderLib for Header global;\n\n/// Types of messages supported by Origin-Destination\n/// - Base: message sent by protocol user, contains tips\n/// - Manager: message sent between AgentManager contracts located on different chains, no tips\nenum MessageFlag {\n    Base,\n    Manager\n}\n\nusing HeaderLib for MessageFlag global;\n\n/// Library for formatting _the header part_ of _the messages used by Origin and Destination_.\n/// - Header represents general information for routing a Message for Origin and Destination.\n/// - Header occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n///\n/// # Header stack layout (from highest bits to lowest)\n///\n/// | Position   | Field            | Type   | Bytes | Description                             |\n/// | ---------- | ---------------- | ------ | ----- | --------------------------------------- |\n/// | (017..016] | flag             | uint8  | 1     | Flag specifying the type of message     |\n/// | (016..012] | origin           | uint32 | 4     | Domain where message originated         |\n/// | (012..008] | nonce            | uint32 | 4     | Message nonce on the origin domain      |\n/// | (008..004] | destination      | uint32 | 4     | Domain where message will be executed   |\n/// | (004..000] | optimisticPeriod | uint32 | 4     | Optimistic period that will be enforced |\nlibrary HeaderLib {\n    /// @dev Amount of bits to shift to flag field\n    uint136 private constant SHIFT_FLAG = 16 * 8;\n    /// @dev Amount of bits to shift to origin field\n    uint136 private constant SHIFT_ORIGIN = 12 * 8;\n    /// @dev Amount of bits to shift to nonce field\n    uint136 private constant SHIFT_NONCE = 8 * 8;\n    /// @dev Amount of bits to shift to destination field\n    uint136 private constant SHIFT_DESTINATION = 4 * 8;\n\n    /// @notice Returns an encoded header with provided fields\n    /// @param origin_              Domain of origin chain\n    /// @param nonce_               Message nonce on origin chain\n    /// @param destination_         Domain of destination chain\n    /// @param optimisticPeriod_    Optimistic period for message execution\n    function encodeHeader(\n        MessageFlag flag_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint32 destination_,\n        uint32 optimisticPeriod_\n    ) internal pure returns (Header) {\n        // All casts below are upcasts, so they are safe\n        // forgefmt: disable-next-item\n        return Header.wrap(\n            uint136(uint8(flag_)) \u003c\u003c SHIFT_FLAG |\n            uint136(origin_) \u003c\u003c SHIFT_ORIGIN |\n            uint136(nonce_) \u003c\u003c SHIFT_NONCE |\n            uint136(destination_) \u003c\u003c SHIFT_DESTINATION |\n            uint136(optimisticPeriod_)\n        );\n    }\n\n    /// @notice Checks that the header is a valid encoded header.\n    function isHeader(uint256 paddedHeader) internal pure returns (bool) {\n        // Check that flag is within range\n        return _flag(paddedHeader) \u003c= uint8(type(MessageFlag).max);\n    }\n\n    /// @notice Wraps the padded encoded request into a Header-typed value.\n    /// @dev The \"padded\" header is simply an encoded header casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded headers\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedHeader) internal pure returns (Header) {\n        // Check that flag is within range\n        if (!isHeader(paddedHeader)) revert FlagOutOfRange();\n        // Casting to uint136 will truncate the highest bits, which is the behavior we want\n        return Header.wrap(uint136(paddedHeader));\n    }\n\n    /// @notice Returns header's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Header header) internal pure returns (bytes32 hashedHeader) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store header in scratch space\n            mstore(0, header)\n            // Compute hash of header padded to 32 bytes\n            hashedHeader := keccak256(0, 32)\n        }\n    }\n\n    // ══════════════════════════════════════════════ HEADER SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns header's flag field\n    function flag(Header header) internal pure returns (MessageFlag) {\n        // We check that flag is within range when wrapping the header, so this cast is safe\n        return MessageFlag(_flag(Header.unwrap(header)));\n    }\n\n    /// @notice Returns header's origin field\n    function origin(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_ORIGIN);\n    }\n\n    /// @notice Returns header's nonce field\n    function nonce(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_NONCE);\n    }\n\n    /// @notice Returns header's destination field\n    function destination(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_DESTINATION);\n    }\n\n    /// @notice Returns header's optimistic seconds field\n    function optimisticPeriod(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns header's flag field without casting to MessageFlag\n    function _flag(uint256 paddedHeader) private pure returns (uint8) {\n        // Casting to uint8 will truncate the highest bits, which is the behavior we want\n        return uint8(paddedHeader \u003e\u003e SHIFT_FLAG);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n     * constructor.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall \u0026\u0026 _initialized \u003c 1) || (!AddressUpgradeable.isContract(address(this)) \u0026\u0026 _initialized == 1),\n            \"Initializable: contract is already initialized\"\n        );\n        _initialized = 1;\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: setting the version to 255 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing \u0026\u0026 _initialized \u003c version, \"Initializable: contract is already initialized\");\n        _initialized = version;\n        _initializing = true;\n        _;\n        _initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        require(_initializing, \"Initializable: contract is not initializing\");\n        _;\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized != type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint8) {\n        return _initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _initializing;\n    }\n}\n\n// contracts/interfaces/IAgentManager.sol\n\ninterface IAgentManager {\n    /**\n     * @notice Allows Inbox to open a Dispute between a Guard and a Notary, if they are both not in Dispute already.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Guard or Notary is already in Dispute.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Allows Inbox to slash an agent, if their fraud was proven.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Domain doesn't match the saved agent domain.\n     * @param domain    Domain where the Agent is active\n     * @param agent     Address of the Agent\n     * @param prover    Address that initially provided fraud proof\n     */\n    function slashAgent(uint32 domain, address agent, address prover) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest known root of the Agent Merkle Tree.\n     */\n    function agentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns the number of opened Disputes.\n     * @dev This includes the Disputes that have been resolved already.\n     */\n    function getDisputesAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns information about the dispute with the given index.\n     * @dev Will revert if dispute with given index hasn't been opened yet.\n     * @param index             Dispute index\n     * @return guard            Address of the Guard in the Dispute\n     * @return notary           Address of the Notary in the Dispute\n     * @return slashedAgent     Address of the Agent who was slashed when Dispute was resolved\n     * @return fraudProver      Address who provided fraud proof to resolve the Dispute\n     * @return reportPayload    Raw payload with report data that led to the Dispute\n     * @return reportSignature  Guard signature for the report payload\n     */\n    function getDispute(uint256 index)\n        external\n        view\n        returns (\n            address guard,\n            address notary,\n            address slashedAgent,\n            address fraudProver,\n            bytes memory reportPayload,\n            bytes memory reportSignature\n        );\n\n    /**\n     * @notice Returns the current Dispute status of a given agent. See Structures.sol for details.\n     * @dev Every returned value will be set to zero if agent was not slashed and is not in Dispute.\n     * `rival` and `disputePtr` will be set to zero if the agent was slashed without being in Dispute.\n     * @param agent         Agent address\n     * @return flag         Flag describing the current Dispute status for the agent: None/Pending/Slashed\n     * @return rival        Address of the rival agent in the Dispute\n     * @return fraudProver  Address who provided fraud proof to resolve the Dispute\n     * @return disputePtr   Index of the opened Dispute PLUS ONE. Zero if agent is not in Dispute.\n     */\n    function disputeStatus(address agent)\n        external\n        view\n        returns (DisputeFlag flag, address rival, address fraudProver, uint256 disputePtr);\n}\n\n// contracts/interfaces/IAgentSecured.sol\n\ninterface IAgentSecured {\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * between a Guard and a Notary has been opened.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * has been resolved due to one of the agents being slashed.\n     * \u003e `rivalIndex` will be ZERO, if the slashed agent was not in the Dispute.\n     * @param slashedIndex  Index of the slashed agent in the Agent Merkle Tree\n     * @param rivalIndex    Index of the their Dispute Rival in the Agent Merkle Tree\n     */\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the address of the local AgentManager contract, which is treated as\n     * the \"source of truth\" for agent statuses.\n     */\n    function agentManager() external view returns (address);\n\n    /**\n     * @notice Returns the address of the local Inbox contract, which is treated as\n     * the \"source of truth\" for agent-signed statements.\n     * @dev Inbox passes verified agent statements to `IAgentSecured` contract.\n     */\n    function inbox() external view returns (address);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns (flag, openedAt, resolvedAt) that describes the latest status of\n     * the latest dispute for an agent with a given index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param agentIndex    Agent index in the Agent Merkle Tree\n     * @return              Latest dispute status for the given agent: (flag, openedAt, resolvedAt)\n     */\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory);\n}\n\n// contracts/libs/memory/ByteString.sol\n\n/// @dev CallData is a memory view over the payload to be used for an external call, i.e.\n/// recipient.call(callData). Its length is always (4 + 32 * N) bytes:\n/// - First 4 bytes represent the function selector.\n/// - 32 * N bytes represent N words that function arguments occupy.\ntype CallData is uint256;\n\n/// @dev Attach library functions to CallData\nusing ByteString for CallData global;\n\n/// @dev Signature is a memory view over a \"65 bytes\" array representing a ECDSA signature.\ntype Signature is uint256;\n\n/// @dev Attach library functions to Signature\nusing ByteString for Signature global;\n\nlibrary ByteString {\n    using MemViewLib for bytes;\n\n    /**\n     * @dev non-compact ECDSA signatures are enforced as of OZ 4.7.3\n     *\n     *      Signature payload memory layout\n     * [000 .. 032) r   bytes32 32 bytes\n     * [032 .. 064) s   bytes32 32 bytes\n     * [064 .. 065) v   uint8    1 byte\n     */\n    uint256 internal constant SIGNATURE_LENGTH = 65;\n    uint256 private constant OFFSET_R = 0;\n    uint256 private constant OFFSET_S = 32;\n    uint256 private constant OFFSET_V = 64;\n\n    /**\n     * @dev Calldata memory layout\n     * [000 .. 004) selector    bytes4  4 bytes\n     *      Optional: N function arguments\n     * [004 .. 036) arg1        bytes32 32 bytes\n     *      ..\n     * [AAA .. END) argN        bytes32 32 bytes\n     */\n    uint256 internal constant SELECTOR_LENGTH = 4;\n    uint256 private constant OFFSET_SELECTOR = 0;\n    uint256 private constant OFFSET_ARGUMENTS = SELECTOR_LENGTH;\n\n    // ═════════════════════════════════════════════════ SIGNATURE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the signature payload from the given values.\n     * @dev Using ByteString.formatSignature({r: r, s: s, v: v}) will make sure\n     * that params are given in the right order.\n     */\n    function formatSignature(bytes32 r, bytes32 s, uint8 v) internal pure returns (bytes memory) {\n        return abi.encodePacked(r, s, v);\n    }\n\n    /**\n     * @notice Returns a Signature view over for the given payload.\n     * @dev Will revert if the payload is not a signature.\n     */\n    function castToSignature(bytes memory payload) internal pure returns (Signature) {\n        return castToSignature(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Signature view.\n     * @dev Will revert if the memory view is not over a signature.\n     */\n    function castToSignature(MemView memView) internal pure returns (Signature) {\n        if (!isSignature(memView)) revert UnformattedSignature();\n        return Signature.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a signature\n     */\n    function isSignature(MemView memView) internal pure returns (bool) {\n        return memView.len() == SIGNATURE_LENGTH;\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Signature signature) internal pure returns (MemView) {\n        return MemView.wrap(Signature.unwrap(signature));\n    }\n\n    // ═════════════════════════════════════════════ SIGNATURE SLICING ═════════════════════════════════════════════════\n\n    /// @notice Unpacks signature payload into (r, s, v) parameters.\n    /// @dev Make sure to verify signature length with isSignature() beforehand.\n    function toRSV(Signature signature) internal pure returns (bytes32 r, bytes32 s, uint8 v) {\n        // Get the underlying memory view\n        MemView memView = unwrap(signature);\n        r = memView.index({index_: OFFSET_R, bytes_: 32});\n        s = memView.index({index_: OFFSET_S, bytes_: 32});\n        // Can be safely casted to uint8, since we index a single byte\n        v = uint8(memView.indexUint({index_: OFFSET_V, bytes_: 1}));\n    }\n\n    // ═════════════════════════════════════════════════ CALLDATA ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the calldata with the modified arguments:\n     * the existing arguments are prepended with the arguments from the prefix.\n     * @dev Given:\n     *  - `calldata = abi.encodeWithSelector(foo.selector, d, e);`\n     *  - `prefix = abi.encode(a, b, c);`\n     *  - `a`, `b`, `c` are arguments of static type (i.e. not dynamically sized ones)\n     *      Then:\n     *  - Function will return abi.encodeWithSelector(foo.selector, a, c, c, d, e)\n     *  - Returned calldata will trigger `foo(a, b, c, d, e)` when used for a contract call.\n     * Note: for clarification as to what types are considered static, see\n     * https://docs.soliditylang.org/en/latest/abi-spec.html#formal-specification-of-the-encoding\n     * @param callData  Calldata that needs to be modified\n     * @param prefix    ABI-encoded arguments to use as the first arguments in the new calldata\n     * @return Modified calldata having prefix as the first arguments.\n     */\n    function addPrefix(CallData callData, bytes memory prefix) internal view returns (bytes memory) {\n        // Prefix should occupy a whole amount of words in memory\n        if (!_fullWords(prefix.length)) revert UnformattedCallDataPrefix();\n        MemView[] memory views = new MemView[](3);\n        // Use payload's function selector\n        views[0] = abi.encodePacked(callData.callSelector()).ref();\n        // Use prefix as the first arguments\n        views[1] = prefix.ref();\n        // Use payload's remaining arguments\n        views[2] = callData.arguments();\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a CallData view over for the given payload.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(bytes memory payload) internal pure returns (CallData) {\n        return castToCallData(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a CallData view.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(MemView memView) internal pure returns (CallData) {\n        if (!isCallData(memView)) revert UnformattedCallData();\n        return CallData.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a valid calldata, i.e.\n     * a function selector, followed by arbitrary amount of arguments.\n     */\n    function isCallData(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Calldata should at least have a function selector\n        if (length \u003c SELECTOR_LENGTH) return false;\n        // The remainder of the calldata should be exactly N memory words (N \u003e= 0)\n        return _fullWords(length - SELECTOR_LENGTH);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(CallData callData) internal pure returns (MemView) {\n        return MemView.wrap(CallData.unwrap(callData));\n    }\n\n    /// @notice Returns callData's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(CallData callData) internal pure returns (bytes32) {\n        return callData.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ CALLDATA SLICING ══════════════════════════════════════════════════\n\n    /**\n     * @notice Returns amount of memory words (32 byte chunks) the function arguments\n     * occupy in the calldata.\n     * @dev This might differ from amount of arguments supplied, if any of the arguments\n     * occupies more than one memory slot. It is true, however, that argument part of the payload\n     * occupies exactly N words, even for dynamic types like `bytes`\n     */\n    function argumentWords(CallData callData) internal pure returns (uint256) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        // Equivalent of (length - SELECTOR_LENGTH) / 32\n        return (memView.len() - SELECTOR_LENGTH) \u003e\u003e 5;\n    }\n\n    /// @notice Returns selector for the provided calldata.\n    function callSelector(CallData callData) internal pure returns (bytes4) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return bytes4(memView.index({index_: OFFSET_SELECTOR, bytes_: SELECTOR_LENGTH}));\n    }\n\n    /// @notice Returns abi encoded arguments for the provided calldata.\n    function arguments(CallData callData) internal pure returns (MemView) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return memView.sliceFrom({index_: OFFSET_ARGUMENTS});\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if length is full amount of memory words (32 bytes).\n    function _fullWords(uint256 length) internal pure returns (bool) {\n        // The equivalent of length % 32 == 0\n        return length \u0026 31 == 0;\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n    function __Context_init() internal onlyInitializing {\n    }\n\n    function __Context_init_unchained() internal onlyInitializing {\n    }\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[50] private __gap;\n}\n\n// contracts/libs/merkle/MerkleTree.sol\n\n/// `BaseTree` is a struct representing incremental merkle tree.\n/// - Contains only the current branch.\n/// - The number of inserted leaves is stored externally, and is later supplied for tree operations.\n/// - Has a fixed height of `ORIGIN_TREE_HEIGHT`.\n/// - Can store up to `2 ** ORIGIN_TREE_HEIGHT - 1` leaves.\n/// \u003e Note: the hash function for the tree `H(x, y)` is defined as:\n/// \u003e - `H(0,0) = 0`\n/// \u003e - `H(x,y) = keccak256(x, y), when (x != 0 || y != 0)`\n/// ## Invariant for leafs\n/// - The leftmost empty leaf has `index == count`, where `count` is the amount of the inserted leafs so far.\n/// - Value for any empty leaf or node is bytes32(0).\n/// ## Invariant for current branch\n/// `branch[i]` is always the value of a node on the i-th level.\n/// Levels are numbered from leafs to root: `0 .. ORIGIN_TREE_HEIGHT`.\n/// `branch[i]` stores the value for the node, such that:\n//  - The node is a \"left child\" (e.g. has an even index).\n/// - The node must have two non-empty children.\n/// - Out of all level's \"left child\" nodes with \"non-empty children\",\n/// the one with the biggest index (the rightmost one) is stored as `branch[i]`.\n/// \u003e __`branch` could be used to form a proof of inclusion for the first empty leaf (`index == count`).__\n/// _Here is how:_\n/// - Let's walk along the path from the \"first empty leaf\" to the root.\n/// - i-th bit of the \"first empty leaf\" index (which is equal to `count`) determines if the path's node\n/// for this i-th level is a \"left child\" or a \"right child\".\n/// - i-th bit in `count` is 0 → we are the left child on this level → sibling is the right child\n/// that does not exist yet → `proof[i] = bytes32(0)`.\n/// - i-th bit in `count` is 1 → we are the right child on this level → sibling is the left child\n/// sibling is the rightmost \"left child\" node on the level → `proof[i] = branch[i]`.\n/// \u003e Therefore `proof[i] = (count \u0026 (1 \u003c\u003c i)) == 0 ? bytes32(0) : branch[i])`\nstruct BaseTree {\n    bytes32[ORIGIN_TREE_HEIGHT] branch;\n}\n\nusing MerkleTree for BaseTree global;\n\n/// `HistoricalTree` is an incremental merkle tree keeping track of its historical merkle roots.\n/// \u003e - `roots[N]` is the root of the tree after `N` leafs were inserted\n/// \u003e - `roots[0] == bytes32(0)`\n/// @param tree     Incremental merkle tree\n/// @param roots    Historical merkle roots of the tree\nstruct HistoricalTree {\n    BaseTree tree;\n    bytes32[] roots;\n}\n\nusing MerkleTree for HistoricalTree global;\n\n/// `DynamicTree` is a struct representing a Merkle Tree with `2**AGENT_TREE_HEIGHT` leaves.\n/// - A single operation is available: update value for leaf with an arbitrary index (which might be a non-empty leaf).\n/// - This is done by requesting the proof of inclusion for the old value, which is used to both\n/// verify the old value, and calculate the new root.\n/// \u003e Based on Original idea from [ER forum post](https://ethresear.ch/t/efficient-on-chain-dynamic-merkle-tree/11054).\nstruct DynamicTree {\n    bytes32 root;\n}\n\nusing MerkleTree for DynamicTree global;\n\n/// MerkleTree is work based on Nomad's Merkle.sol, which is used under MIT OR Apache-2.0\n/// [link](https://github.com/nomad-xyz/monorepo/blob/main/packages/contracts-core/contracts/libs/Merkle.sol).\n/// With the following changes:\n/// - Adapted for Solidity 0.8.x.\n/// - Amount of tree leaves stored externally.\n/// - Added thorough documentation.\n/// - `H(0,0) = 0` optimization from [ER forum post](https://ethresear.ch/t/optimizing-sparse-merkle-trees/3751/6).\n/// \u003e Nomad's Merkle.sol is work based on eth2 deposit contract, which is used under CC0-1.0\n///[link](https://github.com/ethereum/deposit_contract/blob/dev/deposit_contract/contracts/validator_registration.v.py).\n/// With the following changes:\n/// \u003e - Implemented in Solidity 0.7.6 (eth2 deposit contract implemented in Vyper).\n/// \u003e - `H() = keccak256()` is used as the hashing function instead of `sha256()`.\nlibrary MerkleTree {\n    /// @dev For root calculation we need at least one empty leaf, thus the minus one in the formula.\n    uint256 internal constant MAX_LEAVES = 2 ** ORIGIN_TREE_HEIGHT - 1;\n\n    // ═════════════════════════════════════════════════ BASE TREE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Inserts `node` into merkle tree\n     * @dev Reverts if tree is full\n     * @param newCount  Amount of inserted leaves in the tree after the insertion (i.e. current + 1)\n     * @param node      Element to insert into tree\n     */\n    function insertBase(BaseTree storage tree, uint256 newCount, bytes32 node) internal {\n        if (newCount \u003e MAX_LEAVES) revert MerkleTreeFull();\n        // We go up the tree following the branch from the empty leaf AFTER the just inserted one.\n        // We stop when we find the first \"right child\" node.\n        // Its sibling is now the rightmost \"left child\" node that has two non-empty children.\n        // Therefore we need to update `tree.branch` value on this level.\n        // One could see that `tree.branch` value on lower and higher levels remain unchanged.\n\n        // Loop invariant: `node` is the current level's value for the branch from JUST INSERTED leaf\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            if ((newCount \u0026 1) == 1) {\n                // Found the first \"right child\" node on the branch from EMPTY leaf\n                // `node` is the value for node on branch from JUST INSERTED leaf\n                // Which in this case is the \"left child\".\n                // We update tree.branch and exit\n                tree.branch[i] = node;\n                return;\n            }\n            // On the branch from EMPTY leaf this is still a \"left child\".\n            // Meaning on branch from JUST INSERTED leaf, `node` is a right child.\n            // We compute value for `node` parent using `tree.branch` invariant:\n            // This is the rightmost \"left child\" node, which would be sibling of `node`.\n            node = MerkleMath.getParent(tree.branch[i], node);\n            // Get the parent index, and go to the next tree level\n            newCount \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n        // As the loop should always end prematurely with the `return` statement,\n        // this code should be unreachable. We assert `false` just to be safe.\n        assert(false);\n    }\n\n    /**\n     * @notice Calculates and returns current root of the merkle tree.\n     * @param count     Current amount of inserted leaves in the tree\n     * @return current  Calculated root of `tree`\n     */\n    function rootBase(BaseTree storage tree, uint256 count) internal view returns (bytes32 current) {\n        // To calculate the root we follow the branch of first EMPTY leaf (index == count)\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            // Check if we are the left or the right child on the current level\n            if ((count \u0026 1) == 1) {\n                // We are the right child. Our sibling is the \"rightmost\" \"left-child\" node\n                // that has two non-empty children → sibling is `tree.branch[i]`\n                current = MerkleMath.getParent(tree.branch[i], current);\n            } else {\n                // We are the left child. Our sibling does not exist yet → sibling is EMPTY\n                current = MerkleMath.getParent(current, bytes32(0));\n            }\n            // Get the parent index, and go to the next tree level\n            count \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    // ══════════════════════════════════════════════ HISTORICAL TREE ══════════════════════════════════════════════════\n\n    /// @notice Initializes the historical roots for the tree by inserting an empty root.\n    // solhint-disable-next-line ordering\n    function initializeRoots(HistoricalTree storage tree) internal returns (bytes32 savedRoot) {\n        // This should only be called once, when the contract is initialized\n        assert(tree.roots.length == 0);\n        // Save root for empty merkle tree: bytes32(0)\n        tree.roots.push(savedRoot);\n    }\n\n    /// @notice Inserts a new leaf into the merkle tree.\n    /// @dev Reverts if tree is full.\n    /// @param node         Element to insert into tree\n    /// @return newRoot     Merkle root after the leaf was inserted\n    function insert(HistoricalTree storage tree, bytes32 node) internal returns (bytes32 newRoot) {\n        // Tree count after the new leaf will be inserted (we store roots[0] as root of empty tree)\n        uint256 newCount = tree.roots.length;\n        tree.tree.insertBase(newCount, node);\n        // Save the new root\n        newRoot = tree.tree.rootBase(newCount);\n        tree.roots.push(newRoot);\n    }\n\n    /// @notice Returns the historical root of the merkle tree.\n    /// @dev Reverts if not enough leafs have been inserted.\n    /// @param count            Amount of leafs in the tree at some point of time\n    /// @return historicalRoot  Merkle root after `count` leafs were inserted\n    function root(HistoricalTree storage tree, uint256 count) internal view returns (bytes32 historicalRoot) {\n        if (count \u003e= tree.roots.length) revert NotEnoughLeafs();\n        return tree.roots[count];\n    }\n\n    // ═══════════════════════════════════════════════ DYNAMIC TREE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Updates the value for the leaf with the given index in the Dynamic Merkle Tree.\n     * @dev Will revert if incorrect proof of inclusion for old value is supplied.\n     * @param tree          Dynamic merkle tree\n     * @param index         Index of the leaf to update\n     * @param oldValue      Previous value of the leaf\n     * @param branch        Proof of inclusion of previous value into the tree\n     * @param newValue      New leaf value to assign\n     * @return newRoot      New value for the Merkle Root after the leaf is updated\n     */\n    function update(\n        DynamicTree storage tree,\n        uint256 index,\n        bytes32 oldValue,\n        bytes32[] memory branch,\n        bytes32 newValue\n    ) internal returns (bytes32 newRoot) {\n        // Check that the old value + proof result in a correct root\n        if (MerkleMath.proofRoot(index, oldValue, branch, AGENT_TREE_HEIGHT) != tree.root) {\n            revert LeafNotProven();\n        }\n        // New root is new value + the same proof (values for sibling nodes are not updated)\n        newRoot = MerkleMath.proofRoot(index, newValue, branch, AGENT_TREE_HEIGHT);\n        // Write the new root\n        tree.root = newRoot;\n    }\n}\n\n// contracts/libs/stack/Tips.sol\n\n/// Tips is encoded data with \"tips paid for sending a base message\".\n/// Note: even though uint256 is also an underlying type for MemView, Tips is stored ON STACK.\ntype Tips is uint256;\n\nusing TipsLib for Tips global;\n\n/// # Tips\n/// Library for formatting _the tips part_ of _the base messages_.\n///\n/// ## How the tips are awarded\n/// Tips are paid for sending a base message, and are split across all the agents that\n/// made the message execution on destination chain possible.\n/// ### Summit tips\n/// Split between:\n///     - Guard posting a snapshot with state ST_G for the origin chain.\n///     - Notary posting a snapshot SN_N using ST_G. This creates attestation A.\n///     - Notary posting a message receipt after it is executed on destination chain.\n/// ### Attestation tips\n/// Paid to:\n///     - Notary posting attestation A to destination chain.\n/// ### Execution tips\n/// Paid to:\n///     - First executor performing a valid execution attempt (correct proofs, optimistic period over),\n///      using attestation A to prove message inclusion on origin chain, whether the recipient reverted or not.\n/// ### Delivery tips.\n/// Paid to:\n///     - Executor who successfully executed the message on destination chain.\n///\n/// ## Tips encoding\n/// - Tips occupy a single storage word, and thus are stored on stack instead of being stored in memory.\n/// - The actual tip values should be determined by multiplying stored values by divided by TIPS_MULTIPLIER=2**32.\n/// - Tips are packed into a single word of storage, while allowing real values up to ~8*10**28 for every tip category.\n/// \u003e The only downside is that the \"real tip values\" are now multiplies of ~4*10**9, which should be fine even for\n/// the chains with the most expensive gas currency.\n/// # Tips stack layout (from highest bits to lowest)\n///\n/// | Position   | Field          | Type   | Bytes | Description                                                |\n/// | ---------- | -------------- | ------ | ----- | ---------------------------------------------------------- |\n/// | (032..024] | summitTip      | uint64 | 8     | Tip for agents interacting with Summit contract            |\n/// | (024..016] | attestationTip | uint64 | 8     | Tip for Notary posting attestation to Destination contract |\n/// | (016..008] | executionTip   | uint64 | 8     | Tip for valid execution attempt on destination chain       |\n/// | (008..000] | deliveryTip    | uint64 | 8     | Tip for successful message delivery on destination chain   |\n\nlibrary TipsLib {\n    using SafeCast for uint256;\n\n    /// @dev Amount of bits to shift to summitTip field\n    uint256 private constant SHIFT_SUMMIT_TIP = 24 * 8;\n    /// @dev Amount of bits to shift to attestationTip field\n    uint256 private constant SHIFT_ATTESTATION_TIP = 16 * 8;\n    /// @dev Amount of bits to shift to executionTip field\n    uint256 private constant SHIFT_EXECUTION_TIP = 8 * 8;\n\n    // ═══════════════════════════════════════════════════ TIPS ════════════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips with the given fields\n    /// @param summitTip_        Tip for agents interacting with Summit contract, divided by TIPS_MULTIPLIER\n    /// @param attestationTip_   Tip for Notary posting attestation to Destination contract, divided by TIPS_MULTIPLIER\n    /// @param executionTip_     Tip for valid execution attempt on destination chain, divided by TIPS_MULTIPLIER\n    /// @param deliveryTip_      Tip for successful message delivery on destination chain, divided by TIPS_MULTIPLIER\n    function encodeTips(uint64 summitTip_, uint64 attestationTip_, uint64 executionTip_, uint64 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // forgefmt: disable-next-item\n        return Tips.wrap(\n            uint256(summitTip_) \u003c\u003c SHIFT_SUMMIT_TIP |\n            uint256(attestationTip_) \u003c\u003c SHIFT_ATTESTATION_TIP |\n            uint256(executionTip_) \u003c\u003c SHIFT_EXECUTION_TIP |\n            uint256(deliveryTip_)\n        );\n    }\n\n    /// @notice Convenience function to encode tips with uint256 values.\n    function encodeTips256(uint256 summitTip_, uint256 attestationTip_, uint256 executionTip_, uint256 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // In practice, the tips amounts are not supposed to be higher than 2**96, and with 32 bits of granularity\n        // using uint64 is enough to store the values. However, we still check for overflow just in case.\n        // TODO: consider using Number type to store the tips values.\n        return encodeTips({\n            summitTip_: (summitTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            attestationTip_: (attestationTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            executionTip_: (executionTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            deliveryTip_: (deliveryTip_ \u003e\u003e TIPS_GRANULARITY).toUint64()\n        });\n    }\n\n    /// @notice Wraps the padded encoded tips into a Tips-typed value.\n    /// @dev There is no actual padding here, as the underlying type is already uint256,\n    /// but we include this function for consistency and to be future-proof, if tips will eventually use anything\n    /// smaller than uint256.\n    function wrapPadded(uint256 paddedTips) internal pure returns (Tips) {\n        return Tips.wrap(paddedTips);\n    }\n\n    /**\n     * @notice Returns a formatted Tips payload specifying empty tips.\n     * @return Formatted tips\n     */\n    function emptyTips() internal pure returns (Tips) {\n        return Tips.wrap(0);\n    }\n\n    /// @notice Returns tips's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Tips tips) internal pure returns (bytes32 hashedTips) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store tips in scratch space\n            mstore(0, tips)\n            // Compute hash of tips padded to 32 bytes\n            hashedTips := keccak256(0, 32)\n        }\n    }\n\n    // ═══════════════════════════════════════════════ TIPS SLICING ════════════════════════════════════════════════════\n\n    /// @notice Returns summitTip field\n    function summitTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_SUMMIT_TIP);\n    }\n\n    /// @notice Returns attestationTip field\n    function attestationTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_ATTESTATION_TIP);\n    }\n\n    /// @notice Returns executionTip field\n    function executionTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_EXECUTION_TIP);\n    }\n\n    /// @notice Returns deliveryTip field\n    function deliveryTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips));\n    }\n\n    // ════════════════════════════════════════════════ TIPS VALUE ═════════════════════════════════════════════════════\n\n    /// @notice Returns total value of the tips payload.\n    /// This is the sum of the encoded values, scaled up by TIPS_MULTIPLIER\n    function value(Tips tips) internal pure returns (uint256 value_) {\n        value_ = uint256(tips.summitTip()) + tips.attestationTip() + tips.executionTip() + tips.deliveryTip();\n        value_ \u003c\u003c= TIPS_GRANULARITY;\n    }\n\n    /// @notice Increases the delivery tip to match the new value.\n    function matchValue(Tips tips, uint256 newValue) internal pure returns (Tips newTips) {\n        uint256 oldValue = tips.value();\n        if (newValue \u003c oldValue) revert TipsValueTooLow();\n        // We want to increase the delivery tip, while keeping the other tips the same\n        unchecked {\n            uint256 delta = (newValue - oldValue) \u003e\u003e TIPS_GRANULARITY;\n            // `delta` fits into uint224, as TIPS_GRANULARITY is 32, so this never overflows uint256.\n            // In practice, this will never overflow uint64 as well, but we still check it just in case.\n            if (delta + tips.deliveryTip() \u003e type(uint64).max) revert TipsOverflow();\n            // Delivery tips occupy lowest 8 bytes, so we can just add delta to the tips value\n            // to effectively increase the delivery tip (knowing that delta fits into uint64).\n            newTips = Tips.wrap(Tips.unwrap(tips) + delta);\n        }\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    function __Ownable_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable_init_unchained() internal onlyInitializing {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n    function __Ownable2Step_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable2Step_init_unchained() internal onlyInitializing {\n    }\n    address private _pendingOwner;\n\n    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Returns the address of the pending owner.\n     */\n    function pendingOwner() public view virtual returns (address) {\n        return _pendingOwner;\n    }\n\n    /**\n     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual override onlyOwner {\n        _pendingOwner = newOwner;\n        emit OwnershipTransferStarted(owner(), newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual override {\n        delete _pendingOwner;\n        super._transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev The new owner accepts the ownership transfer.\n     */\n    function acceptOwnership() public virtual {\n        address sender = _msgSender();\n        require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n        _transferOwnership(sender);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// contracts/libs/memory/State.sol\n\n/// State is a memory view over a formatted state payload.\ntype State is uint256;\n\nusing StateLib for State global;\n\n/// # State\n/// State structure represents the state of Origin contract at some point of time.\n/// - State is structured in a way to track the updates of the Origin Merkle Tree.\n/// - State includes root of the Origin Merkle Tree, origin domain and some additional metadata.\n/// ## Origin Merkle Tree\n/// Hash of every sent message is inserted in the Origin Merkle Tree, which changes\n/// the value of Origin Merkle Root (which is the root for the mentioned tree).\n/// - Origin has a single Merkle Tree for all messages, regardless of their destination domain.\n/// - This leads to Origin state being updated if and only if a message was sent in a block.\n/// - Origin contract is a \"source of truth\" for states: a state is considered \"valid\" in its Origin,\n/// if it matches the state of the Origin contract after the N-th (nonce) message was sent.\n///\n/// # Memory layout of State fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                    |\n/// | ---------- | ----------- | ------- | ----- | ------------------------------ |\n/// | [000..032) | root        | bytes32 | 32    | Root of the Origin Merkle Tree |\n/// | [032..036) | origin      | uint32  | 4     | Domain where Origin is located |\n/// | [036..040) | nonce       | uint32  | 4     | Amount of sent messages        |\n/// | [040..045) | blockNumber | uint40  | 5     | Block of last sent message     |\n/// | [045..050) | timestamp   | uint40  | 5     | Time of last sent message      |\n/// | [050..062) | gasData     | uint96  | 12    | Gas data for the chain         |\n///\n/// @dev State could be used to form a Snapshot to be signed by a Guard or a Notary.\nlibrary StateLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_ROOT = 0;\n    uint256 private constant OFFSET_ORIGIN = 32;\n    uint256 private constant OFFSET_NONCE = 36;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 40;\n    uint256 private constant OFFSET_TIMESTAMP = 45;\n    uint256 private constant OFFSET_GAS_DATA = 50;\n\n    // ═══════════════════════════════════════════════════ STATE ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted State payload with provided fields\n     * @param root_         New merkle root\n     * @param origin_       Domain of Origin's chain\n     * @param nonce_        Nonce of the merkle root\n     * @param blockNumber_  Block number when root was saved in Origin\n     * @param timestamp_    Block timestamp when root was saved in Origin\n     * @param gasData_      Gas data for the chain\n     * @return Formatted state\n     */\n    function formatState(\n        bytes32 root_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_,\n        GasData gasData_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(root_, origin_, nonce_, blockNumber_, timestamp_, gasData_);\n    }\n\n    /**\n     * @notice Returns a State view over the given payload.\n     * @dev Will revert if the payload is not a state.\n     */\n    function castToState(bytes memory payload) internal pure returns (State) {\n        return castToState(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a State view.\n     * @dev Will revert if the memory view is not over a state.\n     */\n    function castToState(MemView memView) internal pure returns (State) {\n        if (!isState(memView)) revert UnformattedState();\n        return State.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted State.\n    function isState(MemView memView) internal pure returns (bool) {\n        return memView.len() == STATE_LENGTH;\n    }\n\n    /// @notice Returns the hash of a State, that could be later signed by a Guard to signal\n    /// that the state is invalid.\n    function hashInvalid(State state) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(stateInvalidSalt, keccak(state))\n        return state.unwrap().keccakSalted(STATE_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(State state) internal pure returns (MemView) {\n        return MemView.wrap(State.unwrap(state));\n    }\n\n    /// @notice Compares two State structures.\n    function equals(State a, State b) internal pure returns (bool) {\n        // Length of a State payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═══════════════════════════════════════════════ STATE HASHING ═══════════════════════════════════════════════════\n\n    /// @notice Returns the hash of the State.\n    /// @dev We are using the Merkle Root of a tree with two leafs (see below) as state hash.\n    function leaf(State state) internal pure returns (bytes32) {\n        (bytes32 leftLeaf_, bytes32 rightLeaf_) = state.subLeafs();\n        // Final hash is the parent of these leafs\n        return keccak256(bytes.concat(leftLeaf_, rightLeaf_));\n    }\n\n    /// @notice Returns \"sub-leafs\" of the State. Hash of these \"sub leafs\" is going to be used\n    /// as a \"state leaf\" in the \"Snapshot Merkle Tree\".\n    /// This enables proving that leftLeaf = (root, origin) was a part of the \"Snapshot Merkle Tree\",\n    /// by combining `rightLeaf` with the remainder of the \"Snapshot Merkle Proof\".\n    function subLeafs(State state) internal pure returns (bytes32 leftLeaf_, bytes32 rightLeaf_) {\n        MemView memView = state.unwrap();\n        // Left leaf is (root, origin)\n        leftLeaf_ = memView.prefix({len_: OFFSET_NONCE}).keccak();\n        // Right leaf is (metadata), or (nonce, blockNumber, timestamp)\n        rightLeaf_ = memView.sliceFrom({index_: OFFSET_NONCE}).keccak();\n    }\n\n    /// @notice Returns the left \"sub-leaf\" of the State.\n    function leftLeaf(bytes32 root_, uint32 origin_) internal pure returns (bytes32) {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(root_, origin_));\n    }\n\n    /// @notice Returns the right \"sub-leaf\" of the State.\n    function rightLeaf(uint32 nonce_, uint40 blockNumber_, uint40 timestamp_, GasData gasData_)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(nonce_, blockNumber_, timestamp_, gasData_));\n    }\n\n    // ═══════════════════════════════════════════════ STATE SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns a historical Merkle root from the Origin contract.\n    function root(State state) internal pure returns (bytes32) {\n        return state.unwrap().index({index_: OFFSET_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns domain of chain where the Origin contract is deployed.\n    function origin(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns nonce of Origin contract at the time, when `root` was the Merkle root.\n    function nonce(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when `root` was saved in Origin.\n    function blockNumber(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when `root` was saved in Origin.\n    /// @dev This is the timestamp according to the origin chain.\n    function timestamp(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n\n    /// @notice Returns gas data for the chain.\n    function gasData(State state) internal pure returns (GasData) {\n        return GasDataLib.wrapGasData(state.unwrap().indexUint({index_: OFFSET_GAS_DATA, bytes_: GAS_DATA_LENGTH}));\n    }\n}\n\n// contracts/libs/memory/BaseMessage.sol\n\n/// BaseMessage is a memory view over the base message supported by Origin-Destination\ntype BaseMessage is uint256;\n\nusing BaseMessageLib for BaseMessage global;\n\n/// BaseMessage structure represents a base message sent via the Origin-Destination contracts.\n/// - It only contains data relevant to the base message, the rest of data is encoded in the message header.\n/// - `sender` and `recipient` for EVM chains are EVM addresses casted to bytes32, while preserving left-alignment.\n/// - `tips` and `request` parameters are specified by a message sender\n/// \u003e Origin will calculate minimum tips for given request and content length, and will reject messages with tips\n/// lower than that.\n///\n/// # Memory layout of BaseMessage fields\n///\n/// | Position   | Field     | Type    | Bytes | Description                            |\n/// | ---------- | --------- | ------- | ----- | -------------------------------------- |\n/// | [000..032) | tips      | uint256 | 32    | Encoded tips paid on origin chain      |\n/// | [032..064) | sender    | bytes32 | 32    | Sender address on origin chain         |\n/// | [064..096) | recipient | bytes32 | 32    | Recipient address on destination chain |\n/// | [096..116) | request   | uint160 | 20    | Encoded request for message execution  |\n/// | [104..AAA) | content   | bytes   | ??    | Content to be passed to recipient      |\nlibrary BaseMessageLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_TIPS = 0;\n    uint256 private constant OFFSET_SENDER = 32;\n    uint256 private constant OFFSET_RECIPIENT = 64;\n    uint256 private constant OFFSET_REQUEST = OFFSET_RECIPIENT + TIPS_LENGTH;\n    uint256 private constant OFFSET_CONTENT = OFFSET_REQUEST + REQUEST_LENGTH;\n\n    // ═══════════════════════════════════════════════ BASE MESSAGE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted BaseMessage payload with provided fields.\n     * @param tips_         Encoded tips information\n     * @param sender_       Sender address on origin chain\n     * @param recipient_    Recipient address on destination chain\n     * @param request_      Encoded request for message execution\n     * @param content_      Raw content to be passed to recipient on destination chain\n     * @return Formatted base message\n     */\n    function formatBaseMessage(Tips tips_, bytes32 sender_, bytes32 recipient_, Request request_, bytes memory content_)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return abi.encodePacked(tips_, sender_, recipient_, request_, content_);\n    }\n\n    /**\n     * @notice Returns a BaseMessage view over the given payload.\n     * @dev Will revert if the payload is not a base message.\n     */\n    function castToBaseMessage(bytes memory payload) internal pure returns (BaseMessage) {\n        return castToBaseMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a BaseMessage view.\n     * @dev Will revert if the memory view is not over a base message payload.\n     */\n    function castToBaseMessage(MemView memView) internal pure returns (BaseMessage) {\n        if (!isBaseMessage(memView)) revert UnformattedBaseMessage();\n        return BaseMessage.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted BaseMessage.\n    function isBaseMessage(MemView memView) internal pure returns (bool) {\n        // Check if sender, recipient, tips fields exist\n        return (memView.len() \u003e= OFFSET_CONTENT);\n        // Content could be empty, so we don't check that\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(BaseMessage baseMessage) internal pure returns (MemView) {\n        return MemView.wrap(BaseMessage.unwrap(baseMessage));\n    }\n\n    /// @notice Returns baseMessage's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        // We hash \"tips\" and \"everything but tips\" to make tips proofs easier to verify\n        return MerkleMath.getParent(baseMessage.tips().leaf(), baseMessage.bodyLeaf());\n    }\n\n    /// @notice Returns hash for the \"everything but tips\" part of the base message.\n    function bodyLeaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_SENDER}).keccak();\n    }\n\n    // ═══════════════════════════════════════════ BASE MESSAGE SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips paid on origin chain.\n    function tips(BaseMessage baseMessage) internal pure returns (Tips) {\n        return TipsLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_TIPS, bytes_: TIPS_LENGTH})));\n    }\n\n    /// @notice Returns sender address on origin chain.\n    function sender(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_SENDER, bytes_: 32});\n    }\n\n    /// @notice Returns recipient address on destination chain.\n    function recipient(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_RECIPIENT, bytes_: 32});\n    }\n\n    /// @notice Returns an encoded request for message execution on destination chain.\n    function request(BaseMessage baseMessage) internal pure returns (Request) {\n        return RequestLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_REQUEST, bytes_: REQUEST_LENGTH})));\n    }\n\n    /// @notice Returns an untyped memory view over the content to be passed to recipient.\n    function content(BaseMessage baseMessage) internal pure returns (MemView) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_CONTENT});\n    }\n}\n\n// contracts/base/MessagingBase.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for all messaging contracts.\n * - Provides context on the local chain's domain.\n * - Provides ownership functionality.\n * - Will be providing pausing functionality when it is implemented.\n */\nabstract contract MessagingBase is MultiCallable, Versioned, Ownable2StepUpgradeable {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @notice Domain of the local chain, set once upon contract creation\n    uint32 public immutable localDomain;\n    // @notice Domain of the Synapse chain, set once upon contract creation\n    uint32 public immutable synapseDomain;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev gap for upgrade safety\n    uint256[50] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    constructor(string memory version_, uint32 synapseDomain_) Versioned(version_) {\n        localDomain = ChainContext.chainId();\n        synapseDomain = synapseDomain_;\n    }\n\n    // TODO: Implement pausing\n\n    /**\n     * @dev Should be impossible to renounce ownership;\n     * we override OpenZeppelin OwnableUpgradeable's\n     * implementation of renounceOwnership to make it a no-op\n     */\n    function renounceOwnership() public override onlyOwner {} //solhint-disable-line no-empty-blocks\n}\n\n// contracts/libs/memory/Message.sol\n\n/// Message is a memory over over a formatted message payload.\ntype Message is uint256;\n\nusing MessageLib for Message global;\n\n/// Library for formatting the various messages supported by Origin and Destination.\n///\n/// # Message memory layout\n///\n/// | Position   | Field  | Type    | Bytes | Description                                             |\n/// | ---------- | ------ | ------- | ----- | ------------------------------------------------------- |\n/// | [000..017) | header | uint136 | 17    | Encoded general routing information for the message     |\n/// | [017..AAA) | body   | bytes   | ??    | Formatted payload (according to flag) with message body |\nlibrary MessageLib {\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MemViewLib for bytes;\n    using HeaderLib for MemView;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_HEADER = 0;\n    uint256 private constant OFFSET_BODY = OFFSET_HEADER + HEADER_LENGTH;\n\n    // ══════════════════════════════════════════════════ MESSAGE ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns formatted message with provided fields.\n     * @param header_   Encoded general routing information for the message\n     * @param body_     Formatted payload (according to flag) with message body\n     * @return Formatted message\n     */\n    function formatMessage(Header header_, bytes memory body_) internal pure returns (bytes memory) {\n        return abi.encodePacked(header_, body_);\n    }\n\n    /**\n     * @notice Returns a Message view over for the given payload.\n     * @dev Will revert if the payload is not a message payload.\n     */\n    function castToMessage(bytes memory payload) internal pure returns (Message) {\n        return castToMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Message view.\n     * @dev Will revert if the memory view is not over a message payload.\n     */\n    function castToMessage(MemView memView) internal pure returns (Message) {\n        if (!isMessage(memView)) revert UnformattedMessage();\n        return Message.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Message.\n     */\n    function isMessage(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Check if headers exist in the payload\n        if (length \u003c OFFSET_BODY) return false;\n        // Check that Header is valid\n        uint256 paddedHeader = _header(memView);\n        if (!HeaderLib.isHeader(paddedHeader)) return false;\n        // Check that body is formatted according to the flag\n        // Only Base/Manager message flags exist\n        if (HeaderLib.wrapPadded(paddedHeader).flag() == MessageFlag.Base) {\n            // Check if body is a formatted base message\n            return _body(memView).isBaseMessage();\n        } else {\n            // Check if body is a formatted calldata for AgentManager call\n            return _body(memView).isCallData();\n        }\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Message message) internal pure returns (MemView) {\n        return MemView.wrap(Message.unwrap(message));\n    }\n\n    /// @notice Returns message's hash: a leaf to be inserted in the Merkle tree.\n    function leaf(Message message) internal pure returns (bytes32) {\n        // We hash header and body separately to make message proofs easier to verify\n        Header header_ = message.header();\n        // Only Base/Manager message flags exist\n        if (header_.flag() == MessageFlag.Base) {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToBaseMessage().leaf());\n        } else {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToCallData().leaf());\n        }\n    }\n\n    // ══════════════════════════════════════════════ MESSAGE SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns message's encoded header field.\n    function header(Message message) internal pure returns (Header) {\n        return HeaderLib.wrapPadded((message.unwrap().indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH})));\n    }\n\n    /// @notice Returns message's body field as an untyped memory view.\n    function body(Message message) internal pure returns (MemView) {\n        MemView memView = message.unwrap();\n        return _body(memView);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns message's padded header without checking that it is a valid header.\n    function _header(MemView memView) private pure returns (uint256) {\n        return memView.indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH});\n    }\n\n    /// @dev Returns an untyped memory view over the body field without checking\n    /// if the whole payload or the body are properly formatted.\n    function _body(MemView memView) private pure returns (MemView) {\n        return memView.sliceFrom({index_: OFFSET_BODY});\n    }\n}\n\n// contracts/base/AgentSecured.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for messaging contracts that are secured by the agent manager.\n * `AgentSecured` relies on `AgentManager` to provide the following functionality:\n * - Keep track of agents and their statuses.\n * - Pass agent-signed statements that were verified by the agent manager.\n * - These statements are considered valid indefinitely, unless the agent is disputed.\n * - Disputes are opened and resolved by the agent manager.\n * \u003e `AgentSecured` implementation should never use statements signed by agents that are disputed.\n */\nabstract contract AgentSecured is MessagingBase, IAgentSecured {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    address public immutable agentManager;\n\n    /// @inheritdoc IAgentSecured\n    address public immutable inbox;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    // (agent index =\u003e their dispute status: flag, openedAt, resolvedAt)\n    mapping(uint32 =\u003e DisputeStatus) internal _disputes;\n\n    /// @dev gap for upgrade safety\n    uint256[49] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    modifier onlyAgentManager() {\n        if (msg.sender != agentManager) revert CallerNotAgentManager();\n        _;\n    }\n\n    modifier onlyInbox() {\n        if (msg.sender != inbox) revert CallerNotInbox();\n        _;\n    }\n\n    constructor(string memory version_, uint32 synapseDomain_, address agentManager_, address inbox_)\n        MessagingBase(version_, synapseDomain_)\n    {\n        agentManager = agentManager_;\n        inbox = inbox_;\n    }\n\n    // ════════════════════════════════════════════ ONLY AGENT MANAGER ═════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external onlyAgentManager {\n        uint40 openedAt = ChainContext.blockTimestamp();\n        DisputeStatus memory status = DisputeStatus({flag: DisputeFlag.Pending, openedAt: openedAt, resolvedAt: 0});\n        _disputes[guardIndex] = status;\n        _disputes[notaryIndex] = status;\n    }\n\n    /// @inheritdoc IAgentSecured\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external onlyAgentManager {\n        // Update the dispute status of the slashed agent first.\n        uint40 resolvedAt = ChainContext.blockTimestamp();\n        _disputes[slashedIndex].flag = DisputeFlag.Slashed;\n        _disputes[slashedIndex].resolvedAt = resolvedAt;\n        // Mark the rival agent as not disputed, if there was an ongoing dispute.\n        if (rivalIndex != 0) {\n            _disputes[rivalIndex].flag = DisputeFlag.None;\n            _disputes[rivalIndex].resolvedAt = resolvedAt;\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function agentStatus(address agent) external view returns (AgentStatus memory) {\n        return _agentStatus(agent);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status) {\n        return _getAgent(index);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory) {\n        return _disputes[agentIndex];\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns status of the given agent: (flag, domain, index).\n    function _agentStatus(address agent) internal view returns (AgentStatus memory) {\n        return IAgentManager(agentManager).agentStatus(agent);\n    }\n\n    /// @dev Returns agent and their status for a given agent index. Returns zero values for non existing indexes.\n    function _getAgent(uint256 index) internal view returns (address agent, AgentStatus memory status) {\n        return IAgentManager(agentManager).getAgent(index);\n    }\n\n    /// @dev Checks if a Dispute exists for the given Notary. This function returns true, if\n    /// Notary is in ongoing Dispute, or if Dispute was resolved not in Notary's favor.\n    /// In both cases we can't trust Notary's data.\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeExists(uint32 notaryIndex) internal view returns (bool) {\n        return _disputes[notaryIndex].flag != DisputeFlag.None;\n    }\n\n    /// @dev Checks if a Notary recently won a Dispute and is still in the \"post-dispute\" timeout period.\n    /// In this period we still can't trust Notary's data, though we can optimistically assume that\n    /// that the data will be correct after the timeout (assuming no new Disputes are opened).\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeTimeout(uint32 notaryIndex) internal view returns (bool) {\n        DisputeStatus memory status = _disputes[notaryIndex];\n        // Exit early if Notary is in ongoing Dispute / slashed.\n        if (status.flag != DisputeFlag.None) return false;\n        // Check if Notary has been in any Dispute at all.\n        if (status.openedAt == 0) return false;\n        // Otherwise check if the Dispute timeout is still active.\n        return block.timestamp \u003c status.resolvedAt + DISPUTE_TIMEOUT_NOTARY;\n    }\n}\n\n// contracts/hubs/StateHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StateHub` is a parent contract for `Origin`. It is responsible for the following:\n/// - Keeping track of the historical Origin Merkle Tree containing all the message hashes.\n/// - Keeping track of the historical Origin States, as well as verifying their validity.\nabstract contract StateHub is AgentSecured, StateHubEvents, IStateHub {\n    using SafeCast for uint256;\n    using StateLib for bytes;\n\n    struct OriginState {\n        uint40 blockNumber;\n        uint40 timestamp;\n        GasData gasData;\n    }\n    // Bits left for tight packing: 80\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Historical Merkle Tree\n    /// Note: Takes two storage slots\n    HistoricalTree private _tree;\n\n    /// @dev All historical contract States\n    OriginState[] private _originStates;\n\n    /// @dev gap for upgrade safety\n    uint256[47] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IStateHub\n    function isValidState(bytes memory statePayload) external view returns (bool isValid) {\n        // This will revert if payload is not a formatted state\n        State state = statePayload.castToState();\n        return _isValidState(state);\n    }\n\n    /// @inheritdoc IStateHub\n    function statesAmount() external view returns (uint256) {\n        return _originStates.length;\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestLatestState() external view returns (bytes memory stateData) {\n        // This never underflows, assuming the contract was initialized\n        return suggestState(_nextNonce() - 1);\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestState(uint32 nonce) public view returns (bytes memory stateData) {\n        // This will revert if nonce is out of range\n        bytes32 root = _tree.root(nonce);\n        return _formatOriginState(_originStates[nonce], root, localDomain, nonce);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Initializes the saved states list by inserting a state for an empty Merkle Tree.\n    function _initializeStates() internal {\n        // This should only be called once, when the contract is initialized\n        // This will revert if _tree.roots is non-empty\n        bytes32 savedRoot = _tree.initializeRoots();\n        // Save root for empty merkle _tree with block number and timestamp of initialization\n        _saveState(savedRoot, _toOriginState());\n    }\n\n    /// @dev Inserts leaf into the Merkle Tree and saves the updated origin State.\n    function _insertAndSave(bytes32 leaf) internal {\n        bytes32 newRoot = _tree.insert(leaf);\n        _saveState(newRoot, _toOriginState());\n    }\n\n    /// @dev Saves an updated state of the Origin contract\n    function _saveState(bytes32 root, OriginState memory state) internal {\n        uint32 nonce = _nextNonce();\n        _originStates.push(state);\n        // Emit event with raw state data\n        emit StateSaved(_formatOriginState(state, root, localDomain, nonce));\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns nonce of the next sent message: the amount of saved States so far.\n    /// This always equals to \"total amount of sent messages\" plus 1.\n    function _nextNonce() internal view returns (uint32) {\n        // TODO: consider using more than 32 bits for origin nonces\n        return _originStates.length.toUint32();\n    }\n\n    /// @dev Checks if a state is valid, i.e. if it matches the historical one.\n    /// Reverts, if state refers to another Origin contract.\n    function _isValidState(State state) internal view returns (bool) {\n        // Check if state refers to this contract\n        if (state.origin() != localDomain) revert IncorrectOriginDomain();\n        // Check if nonce exists\n        uint32 nonce = state.nonce();\n        if (nonce \u003e= _originStates.length) return false;\n        // Check if state root matches the historical one\n        if (state.root() != _tree.root(nonce)) return false;\n        // Check if state metadata matches the historical one\n        return _areEqual(state, _originStates[nonce]);\n    }\n\n    // ═════════════════════════════════════════════ STRUCT FORMATTING ═════════════════════════════════════════════════\n\n    /// @dev Returns a formatted payload for a stored OriginState.\n    function _formatOriginState(OriginState memory originState, bytes32 root, uint32 origin, uint32 nonce)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return StateLib.formatState({\n            root_: root,\n            origin_: origin,\n            nonce_: nonce,\n            blockNumber_: originState.blockNumber,\n            timestamp_: originState.timestamp,\n            gasData_: originState.gasData\n        });\n    }\n\n    /// @dev Child contract should implement the logic for getting the current gas data from the gas oracle\n    /// to be saved as part of the Origin State.\n    // solhint-disable-next-line ordering\n    function _fetchGasData() internal view virtual returns (GasData);\n\n    /// @dev Returns a OriginState struct to save in the contract.\n    function _toOriginState() internal view returns (OriginState memory originState) {\n        originState.blockNumber = ChainContext.blockNumber();\n        originState.timestamp = ChainContext.blockTimestamp();\n        originState.gasData = _fetchGasData();\n    }\n\n    /// @dev Checks that a state and its Origin representation are equal.\n    function _areEqual(State state, OriginState memory originState) internal pure returns (bool) {\n        return state.blockNumber() == originState.blockNumber \u0026\u0026 state.timestamp() == originState.timestamp;\n    }\n}\n\n// contracts/Origin.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Origin` contract is used for sending messages to remote chains. It is done\n/// by inserting the message hashes into the Origin Merkle, which makes it possible to\n/// prove that message was sent using the Merkle proof against the Origin Merkle Root. This essentially\n/// compresses the list of messages into a single 32-byte value that needs to be stored on the destination chain.\n/// `Origin` is responsible for the following:\n/// - Formatting the sent message payloads, and inserting their hashes into the Origin Merkle Tree.\n/// - Keeping track of its own historical states (see parent contract `StateHub`).\n/// - Enforcing minimum tip values for sent base messages based on the provided execution requests.\n/// - Distributing the collected tips upon request from a local `AgentManager` contract.\ncontract Origin is StateHub, OriginEvents, InterfaceOrigin {\n    using MemViewLib for bytes;\n    using MessageLib for bytes;\n    using TipsLib for bytes;\n    using TypeCasts for address;\n\n    address public immutable gasOracle;\n\n    modifier onlyRemoteDestination(uint32 destination) {\n        if (destination == localDomain) revert IncorrectDestinationDomain();\n        _;\n    }\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_, address gasOracle_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {\n        gasOracle = gasOracle_;\n    }\n\n    /// @notice Initializes Origin contract:\n    /// - msg.sender is set as contract owner\n    /// - State of \"empty merkle tree\" is saved\n    function initialize() external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize \"states\": state of an \"empty merkle tree\" is saved\n        _initializeStates();\n    }\n\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable onlyRemoteDestination(destination) returns (uint32 messageNonce, bytes32 messageHash) {\n        // Check that content is not too large\n        if (content.length \u003e MAX_CONTENT_BYTES) revert ContentLengthTooBig();\n        // This will revert if msg.value is lower than value of minimum tips\n        Tips tips = _getMinimumTips(destination, paddedRequest, content.length).matchValue(msg.value);\n        Request request = RequestLib.wrapPadded(paddedRequest);\n        // Format the BaseMessage body\n        bytes memory body = BaseMessageLib.formatBaseMessage({\n            sender_: msg.sender.addressToBytes32(),\n            recipient_: recipient,\n            tips_: tips,\n            request_: request,\n            content_: content\n        });\n        // Send the message\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Base, body);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        onlyAgentManager\n        onlyRemoteDestination(destination)\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // AgentManager (checked via modifier) is responsible for constructing the calldata payload correctly.\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Manager, payload);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function withdrawTips(address recipient, uint256 amount) external onlyAgentManager {\n        if (address(this).balance \u003c amount) revert InsufficientEthBalance();\n        (bool success,) = recipient.call{value: amount}(\"\");\n        if (!success) revert EthTransferFailed();\n        emit TipWithdrawalCompleted(recipient, amount);\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue)\n    {\n        return _getMinimumTips(destination, paddedRequest, contentLength).value();\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Sends the given message to the specified destination. Message hash is inserted\n    /// into the Origin Merkle Tree, which will enable message execution on destination chain.\n    function _sendMessage(uint32 destination, uint32 optimisticPeriod, MessageFlag flag, bytes memory body)\n        internal\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // Format the message header\n        messageNonce = _nextNonce();\n        Header header = flag.encodeHeader({\n            origin_: localDomain,\n            nonce_: messageNonce,\n            destination_: destination,\n            optimisticPeriod_: optimisticPeriod\n        });\n        // Format the full message payload\n        bytes memory msgPayload = MessageLib.formatMessage(header, body);\n        // Insert new leaf into the Origin Merkle Tree and save the updated state\n        messageHash = msgPayload.castToMessage().leaf();\n        _insertAndSave(messageHash);\n        // Emit event with message information\n        emit Sent(messageHash, messageNonce, destination, msgPayload);\n        // Update the gas oracle data. We do this after the provided tips are checked so that\n        // the provided message is sent in the event that the gas oracle data is updated to a higher value.\n        InterfaceGasOracle(gasOracle).updateGasData(destination);\n        // TODO: consider doing this before the message is sent, while adjusting GasOracle.getMinimumTips() to\n        // use the pending gas oracle data.\n    }\n\n    /// @dev Returns the minimum tips for sending a message to the given destination with the given request and content.\n    function _getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        internal\n        view\n        returns (Tips)\n    {\n        return\n            TipsLib.wrapPadded(InterfaceGasOracle(gasOracle).getMinimumTips(destination, paddedRequest, contentLength));\n    }\n\n    /// @dev Gets the current gas data from the gas oracle to be saved as part of the Origin State.\n    function _fetchGasData() internal view override returns (GasData) {\n        return GasDataLib.wrapGasData(InterfaceGasOracle(gasOracle).getGasData());\n    }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[{"internalType":"uint32","name":"destination","type":"uint32"},{"internalType":"uint256","name":"paddedRequest","type":"uint256"},{"internalType":"uint256","name":"contentLength","type":"uint256"}],"name":"getMinimumTipsValue","outputs":[{"internalType":"uint256","name":"tipsValue","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"destination","type":"uint32"},{"internalType":"bytes32","name":"recipient","type":"bytes32"},{"internalType":"uint32","name":"optimisticPeriod","type":"uint32"},{"internalType":"uint256","name":"paddedRequest","type":"uint256"},{"internalType":"bytes","name":"content","type":"bytes"}],"name":"sendBaseMessage","outputs":[{"internalType":"uint32","name":"messageNonce","type":"uint32"},{"internalType":"bytes32","name":"messageHash","type":"bytes32"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint32","name":"destination","type":"uint32"},{"internalType":"uint32","name":"optimisticPeriod","type":"uint32"},{"internalType":"bytes","name":"payload","type":"bytes"}],"name":"sendManagerMessage","outputs":[{"internalType":"uint32","name":"messageNonce","type":"uint32"},{"internalType":"bytes32","name":"messageHash","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawTips","outputs":[],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{"getMinimumTipsValue(uint32,uint256,uint256)":{"notice":"Returns the minimum tips value for sending a message to a given destination."},"sendBaseMessage(uint32,bytes32,uint32,uint256,bytes)":{"notice":"Send a message to the recipient located on destination domain."},"sendManagerMessage(uint32,uint32,bytes)":{"notice":"Send a manager message to the destination domain."},"withdrawTips(address,uint256)":{"notice":"Withdraws locked base message tips to the recipient."}},"version":1},"developerDoc":{"kind":"dev","methods":{"getMinimumTipsValue(uint32,uint256,uint256)":{"details":"Using at least `tipsValue` as `msg.value` for `sendBaseMessage()` will guarantee that the message will be accepted.","params":{"contentLength":"The length of the message content","destination":"Domain of destination chain","paddedRequest":"Padded encoded message execution request on destination chain"},"returns":{"tipsValue":"       Minimum tips value for a message to be accepted"}},"sendBaseMessage(uint32,bytes32,uint32,uint256,bytes)":{"details":"Recipient has to conform to IMessageRecipient interface, otherwise message won't be delivered. Will revert if any of these is true: - `destination` is equal to contract's local domain - `content` length is greater than `MAX_CONTENT_BYTES` - `msg.value` is lower than value of minimum tips for the given message","params":{"content":"Raw bytes content of message","destination":"Domain of destination chain","optimisticPeriod":"Optimistic period for message execution on destination chain","paddedRequest":"Padded encoded message execution request on destination chain","recipient":"Address of recipient on destination chain as bytes32"},"returns":{"messageHash":"         Hash of the sent message","messageNonce":"        Nonce of the sent message"}},"sendManagerMessage(uint32,uint32,bytes)":{"details":"This could only be called by AgentManager, which takes care of encoding the calldata payload. Note: (msgOrigin, proofMaturity) security args will be added to payload on the destination chain so that the AgentManager could verify where the Manager Message came from and how mature is the proof. Note: function is not payable, as no tips are required for sending a manager message. Will revert if `destination` is equal to contract's local domain.","params":{"destination":"Domain of destination chain","optimisticPeriod":"Optimistic period for message execution on destination chain","payload":"Payload for calling AgentManager on destination chain (with extra security args)"}},"withdrawTips(address,uint256)":{"details":"Could only be called by a local AgentManager.","params":{"amount":"Tips value to withdraw","recipient":"Address to withdraw tips to"}}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"destination\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"paddedRequest\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"contentLength\",\"type\":\"uint256\"}],\"name\":\"getMinimumTipsValue\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"tipsValue\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"destination\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"recipient\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"optimisticPeriod\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"paddedRequest\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"content\",\"type\":\"bytes\"}],\"name\":\"sendBaseMessage\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"messageNonce\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"destination\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"optimisticPeriod\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"name\":\"sendManagerMessage\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"messageNonce\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawTips\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"getMinimumTipsValue(uint32,uint256,uint256)\":{\"details\":\"Using at least `tipsValue` as `msg.value` for `sendBaseMessage()` will guarantee that the message will be accepted.\",\"params\":{\"contentLength\":\"The length of the message content\",\"destination\":\"Domain of destination chain\",\"paddedRequest\":\"Padded encoded message execution request on destination chain\"},\"returns\":{\"tipsValue\":\"       Minimum tips value for a message to be accepted\"}},\"sendBaseMessage(uint32,bytes32,uint32,uint256,bytes)\":{\"details\":\"Recipient has to conform to IMessageRecipient interface, otherwise message won't be delivered. Will revert if any of these is true: - `destination` is equal to contract's local domain - `content` length is greater than `MAX_CONTENT_BYTES` - `msg.value` is lower than value of minimum tips for the given message\",\"params\":{\"content\":\"Raw bytes content of message\",\"destination\":\"Domain of destination chain\",\"optimisticPeriod\":\"Optimistic period for message execution on destination chain\",\"paddedRequest\":\"Padded encoded message execution request on destination chain\",\"recipient\":\"Address of recipient on destination chain as bytes32\"},\"returns\":{\"messageHash\":\"         Hash of the sent message\",\"messageNonce\":\"        Nonce of the sent message\"}},\"sendManagerMessage(uint32,uint32,bytes)\":{\"details\":\"This could only be called by AgentManager, which takes care of encoding the calldata payload. Note: (msgOrigin, proofMaturity) security args will be added to payload on the destination chain so that the AgentManager could verify where the Manager Message came from and how mature is the proof. Note: function is not payable, as no tips are required for sending a manager message. Will revert if `destination` is equal to contract's local domain.\",\"params\":{\"destination\":\"Domain of destination chain\",\"optimisticPeriod\":\"Optimistic period for message execution on destination chain\",\"payload\":\"Payload for calling AgentManager on destination chain (with extra security args)\"}},\"withdrawTips(address,uint256)\":{\"details\":\"Could only be called by a local AgentManager.\",\"params\":{\"amount\":\"Tips value to withdraw\",\"recipient\":\"Address to withdraw tips to\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"getMinimumTipsValue(uint32,uint256,uint256)\":{\"notice\":\"Returns the minimum tips value for sending a message to a given destination.\"},\"sendBaseMessage(uint32,bytes32,uint32,uint256,bytes)\":{\"notice\":\"Send a message to the recipient located on destination domain.\"},\"sendManagerMessage(uint32,uint32,bytes)\":{\"notice\":\"Send a manager message to the destination domain.\"},\"withdrawTips(address,uint256)\":{\"notice\":\"Withdraws locked base message tips to the recipient.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Origin.sol\":\"InterfaceOrigin\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Origin.sol\":{\"keccak256\":\"0x96775924f147f3d1f8df8cdf56731fe52a15af8d8e12e608efb8158c112b18cd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e642a27f5fab3c62b4c02e9754e9e42b1cf2e5381dbea9d3d106d23b7772ebe6\",\"dweb:/ipfs/QmUwn7ZyBvPkjnMuK8ZMSexBUdNQnVtxwyoAyT4DXLQjra\"]}},\"version\":1}"},"hashes":{"getMinimumTipsValue(uint32,uint256,uint256)":"4fc6ad85","sendBaseMessage(uint32,bytes32,uint32,uint256,bytes)":"873661bd","sendManagerMessage(uint32,uint32,bytes)":"a1c702a7","withdrawTips(address,uint256)":"4e04e7a7"}},"solidity/Origin.sol:MemViewLib":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212205522c48dc539430082abb077e24689acf5de59983ce6fdab6967ab36a9fcd80f64736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212205522c48dc539430082abb077e24689acf5de59983ce6fdab6967ab36a9fcd80f64736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/OriginEvents.sol\n\n/// @notice A collection of events emitted by the Origin contract\nabstract contract OriginEvents {\n    /**\n     * @notice Emitted when a new message is sent.\n     * @param messageHash   Hash of message; the leaf inserted to the Merkle tree for the message\n     * @param nonce         Nonce of sent message (starts from 1)\n     * @param destination   Destination domain\n     * @param message       Raw bytes of message\n     */\n    event Sent(bytes32 indexed messageHash, uint32 indexed nonce, uint32 indexed destination, bytes message);\n\n    /**\n     * @notice Emitted when a tip withdrawal is completed.\n     * @param actor     Actor address\n     * @param tip       Tip value, denominated in local domain's wei\n     */\n    event TipWithdrawalCompleted(address actor, uint256 tip);\n}\n\n// contracts/events/StateHubEvents.sol\n\n/// @notice A collection of events emitted by the StateHub contract\nabstract contract StateHubEvents {\n    /**\n     * @notice Emitted when a new Origin State is saved after a message was sent.\n     * @param state     Raw payload with state data\n     */\n    event StateSaved(bytes state);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n    /**\n     * @notice Check that a given state is valid: matches the historical state of Origin contract.\n     * Note: any Agent including an invalid state in their snapshot will be slashed\n     * upon providing the snapshot and agent signature for it to Origin contract.\n     * @dev Will revert if any of these is true:\n     *  - State payload is not properly formatted.\n     * @param statePayload      Raw payload with state data\n     * @return isValid          Whether the provided state is valid\n     */\n    function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns the amount of saved states so far.\n     * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n     */\n    function statesAmount() external view returns (uint256);\n\n    /**\n     * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @return statePayload     Raw payload with the latest state data\n     */\n    function suggestLatestState() external view returns (bytes memory statePayload);\n\n    /**\n     * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @param nonce             Historical nonce to form a state\n     * @return statePayload     Raw payload with historical state data\n     */\n    function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/InterfaceGasOracle.sol\n\ninterface InterfaceGasOracle {\n    /**\n     * @notice Fetches the latest gas data for the chain from `Destination` contract,\n     * and uses it to update the oracle values for the requested chain.\n     * @param domain    Domain to update the gas data for\n     */\n    function updateGasData(uint32 domain) external;\n\n    /**\n     * @notice Returns the gas data for the local chain.\n     */\n    function getGasData() external view returns (uint256 paddedGasData);\n\n    /**\n     * @notice Returns the gas data for the given domain, in the decoded format.\n     * @param domain        Domain of chain to get gas data for\n     * @return gasPrice     Gas price for the chain (in Wei per gas unit)\n     * @return dataPrice    Calldata price (in Wei per byte of content)\n     * @return execBuffer   Tx fee safety buffer for message execution (in Wei)\n     * @return amortAttCost Amortized cost for attestation submission (in Wei)\n     * @return etherPrice   Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n     * @return markup       Markup for the message execution (in BWAD)\n     */\n    function getDecodedGasData(uint32 domain)\n        external\n        view\n        returns (\n            uint256 gasPrice,\n            uint256 dataPrice,\n            uint256 execBuffer,\n            uint256 amortAttCost,\n            uint256 etherPrice,\n            uint256 markup\n        );\n\n    /**\n     * @notice Returns the minimum tips for sending a message to a given destination.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return paddedTips       Padded encoded minimum tips information\n     */\n    function getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 paddedTips);\n}\n\n// contracts/interfaces/InterfaceOrigin.sol\n\ninterface InterfaceOrigin {\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /**\n     * @notice Send a message to the recipient located on destination domain.\n     * @dev Recipient has to conform to IMessageRecipient interface, otherwise message won't be delivered.\n     * Will revert if any of these is true:\n     * - `destination` is equal to contract's local domain\n     * - `content` length is greater than `MAX_CONTENT_BYTES`\n     * - `msg.value` is lower than value of minimum tips for the given message\n     * @param destination           Domain of destination chain\n     * @param recipient             Address of recipient on destination chain as bytes32\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param paddedRequest         Padded encoded message execution request on destination chain\n     * @param content               Raw bytes content of message\n     * @return messageNonce         Nonce of the sent message\n     * @return messageHash          Hash of the sent message\n     */\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable returns (uint32 messageNonce, bytes32 messageHash);\n\n    /**\n     * @notice Send a manager message to the destination domain.\n     * @dev This could only be called by AgentManager, which takes care of encoding the calldata payload.\n     * Note: (msgOrigin, proofMaturity) security args will be added to payload on the destination chain\n     * so that the AgentManager could verify where the Manager Message came from and how mature is the proof.\n     * Note: function is not payable, as no tips are required for sending a manager message.\n     * Will revert if `destination` is equal to contract's local domain.\n     * @param destination           Domain of destination chain\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param payload               Payload for calling AgentManager on destination chain (with extra security args)\n     */\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        returns (uint32 messageNonce, bytes32 messageHash);\n\n    // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Withdraws locked base message tips to the recipient.\n     * @dev Could only be called by a local AgentManager.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function withdrawTips(address recipient, uint256 amount) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the minimum tips value for sending a message to a given destination.\n     * @dev Using at least `tipsValue` as `msg.value` for `sendBaseMessage()`\n     * will guarantee that the message will be accepted.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return tipsValue        Minimum tips value for a message to be accepted\n     */\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue);\n}\n\n// contracts/libs/Constants.sol\n\n// Here we define common constants to enable their easier reusing later.\n\n// ══════════════════════════════════ MERKLE ═══════════════════════════════════\n/// @dev Height of the Agent Merkle Tree\nuint256 constant AGENT_TREE_HEIGHT = 32;\n/// @dev Height of the Origin Merkle Tree\nuint256 constant ORIGIN_TREE_HEIGHT = 32;\n/// @dev Height of the Snapshot Merkle Tree. Allows up to 64 leafs, e.g. up to 32 states\nuint256 constant SNAPSHOT_TREE_HEIGHT = 6;\n// ══════════════════════════════════ STRUCTS ══════════════════════════════════\n/// @dev See Attestation.sol: (bytes32,bytes32,uint32,uint40,uint40): 32+32+4+5+5\nuint256 constant ATTESTATION_LENGTH = 78;\n/// @dev See GasData.sol: (uint16,uint16,uint16,uint16,uint16,uint16): 2+2+2+2+2+2\nuint256 constant GAS_DATA_LENGTH = 12;\n/// @dev See Receipt.sol: (uint32,uint32,bytes32,bytes32,uint8,address,address,address): 4+4+32+32+1+20+20+20\nuint256 constant RECEIPT_LENGTH = 133;\n/// @dev See State.sol: (bytes32,uint32,uint32,uint40,uint40,GasData): 32+4+4+5+5+len(GasData)\nuint256 constant STATE_LENGTH = 50 + GAS_DATA_LENGTH;\n/// @dev Maximum amount of states in a single snapshot. Each state produces two leafs in the tree\nuint256 constant SNAPSHOT_MAX_STATES = 1 \u003c\u003c (SNAPSHOT_TREE_HEIGHT - 1);\n// ══════════════════════════════════ MESSAGE ══════════════════════════════════\n/// @dev See Header.sol: (uint8,uint32,uint32,uint32,uint32): 1+4+4+4+4\nuint256 constant HEADER_LENGTH = 17;\n/// @dev See Request.sol: (uint96,uint64,uint32): 12+8+4\nuint256 constant REQUEST_LENGTH = 24;\n/// @dev See Tips.sol: (uint64,uint64,uint64,uint64): 8+8+8+8\nuint256 constant TIPS_LENGTH = 32;\n/// @dev The amount of discarded last bits when encoding tip values\nuint256 constant TIPS_GRANULARITY = 32;\n/// @dev Tip values could be only the multiples of TIPS_MULTIPLIER\nuint256 constant TIPS_MULTIPLIER = 1 \u003c\u003c TIPS_GRANULARITY;\n// ══════════════════════════════ STATEMENT SALTS ══════════════════════════════\n/// @dev Salts for signing various statements\nbytes32 constant ATTESTATION_VALID_SALT = keccak256(\"ATTESTATION_VALID_SALT\");\nbytes32 constant ATTESTATION_INVALID_SALT = keccak256(\"ATTESTATION_INVALID_SALT\");\nbytes32 constant RECEIPT_VALID_SALT = keccak256(\"RECEIPT_VALID_SALT\");\nbytes32 constant RECEIPT_INVALID_SALT = keccak256(\"RECEIPT_INVALID_SALT\");\nbytes32 constant SNAPSHOT_VALID_SALT = keccak256(\"SNAPSHOT_VALID_SALT\");\nbytes32 constant STATE_INVALID_SALT = keccak256(\"STATE_INVALID_SALT\");\n// ═════════════════════════════════ PROTOCOL ══════════════════════════════════\n/// @dev Optimistic period for new agent roots in LightManager\nuint32 constant AGENT_ROOT_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Timeout between the agent root could be proposed and resolved in LightManager\nuint32 constant AGENT_ROOT_PROPOSAL_TIMEOUT = 12 hours;\nuint32 constant BONDING_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Amount of time that the Notary will not be considered active after they won a dispute\nuint32 constant DISPUTE_TIMEOUT_NOTARY = 12 hours;\n/// @dev Amount of time without fresh data from Notaries before contract owner can resolve stuck disputes manually\nuint256 constant FRESH_DATA_TIMEOUT = 4 hours;\n/// @dev Maximum bytes per message = 2 KiB (somewhat arbitrarily set to begin)\nuint256 constant MAX_CONTENT_BYTES = 2 * 2 ** 10;\n/// @dev Maximum value for the summit tip that could be set in GasOracle\nuint256 constant MAX_SUMMIT_TIP = 0.01 ether;\n\n// contracts/libs/Errors.sol\n\n// ══════════════════════════════ INVALID CALLER ═══════════════════════════════\n\nerror CallerNotAgentManager();\nerror CallerNotDestination();\nerror CallerNotInbox();\nerror CallerNotSummit();\n\n// ══════════════════════════════ INCORRECT DATA ═══════════════════════════════\n\nerror IncorrectAttestation();\nerror IncorrectAgentDomain();\nerror IncorrectAgentIndex();\nerror IncorrectAgentProof();\nerror IncorrectAgentRoot();\nerror IncorrectDataHash();\nerror IncorrectDestinationDomain();\nerror IncorrectOriginDomain();\nerror IncorrectSnapshotProof();\nerror IncorrectSnapshotRoot();\nerror IncorrectState();\nerror IncorrectStatesAmount();\nerror IncorrectTipsProof();\nerror IncorrectVersionLength();\n\nerror IncorrectNonce();\nerror IncorrectSender();\nerror IncorrectRecipient();\n\nerror FlagOutOfRange();\nerror IndexOutOfRange();\nerror NonceOutOfRange();\n\nerror OutdatedNonce();\n\nerror UnformattedAttestation();\nerror UnformattedAttestationReport();\nerror UnformattedBaseMessage();\nerror UnformattedCallData();\nerror UnformattedCallDataPrefix();\nerror UnformattedMessage();\nerror UnformattedReceipt();\nerror UnformattedReceiptReport();\nerror UnformattedSignature();\nerror UnformattedSnapshot();\nerror UnformattedState();\nerror UnformattedStateReport();\n\n// ═══════════════════════════════ MERKLE TREES ════════════════════════════════\n\nerror LeafNotProven();\nerror MerkleTreeFull();\nerror NotEnoughLeafs();\nerror TreeHeightTooLow();\n\n// ═════════════════════════════ OPTIMISTIC PERIOD ═════════════════════════════\n\nerror BaseClientOptimisticPeriod();\nerror MessageOptimisticPeriod();\nerror SlashAgentOptimisticPeriod();\nerror WithdrawTipsOptimisticPeriod();\nerror ZeroProofMaturity();\n\n// ═══════════════════════════════ AGENT MANAGER ═══════════════════════════════\n\nerror AgentNotGuard();\nerror AgentNotNotary();\n\nerror AgentCantBeAdded();\nerror AgentNotActive();\nerror AgentNotActiveNorUnstaking();\nerror AgentNotFraudulent();\nerror AgentNotUnstaking();\nerror AgentUnknown();\n\nerror AgentRootNotProposed();\nerror AgentRootTimeoutNotOver();\n\nerror NotStuck();\n\nerror DisputeAlreadyResolved();\nerror DisputeNotOpened();\nerror DisputeTimeoutNotOver();\nerror GuardInDispute();\nerror NotaryInDispute();\n\nerror MustBeSynapseDomain();\nerror SynapseDomainForbidden();\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\nerror AlreadyExecuted();\nerror AlreadyFailed();\nerror DuplicatedSnapshotRoot();\nerror IncorrectMagicValue();\nerror GasLimitTooLow();\nerror GasSuppliedTooLow();\n\n// ══════════════════════════════════ ORIGIN ═══════════════════════════════════\n\nerror ContentLengthTooBig();\nerror EthTransferFailed();\nerror InsufficientEthBalance();\n\n// ════════════════════════════════ GAS ORACLE ═════════════════════════════════\n\nerror LocalGasDataNotSet();\nerror RemoteGasDataNotSet();\n\n// ═══════════════════════════════════ TIPS ════════════════════════════════════\n\nerror SummitTipTooHigh();\nerror TipsClaimMoreThanEarned();\nerror TipsClaimZero();\nerror TipsOverflow();\nerror TipsValueTooLow();\n\n// ════════════════════════════════ MEMORY VIEW ════════════════════════════════\n\nerror IndexedTooMuch();\nerror ViewOverrun();\nerror OccupiedMemory();\nerror UnallocatedMemory();\nerror PrecompileOutOfGas();\n\n// ═════════════════════════════════ MULTICALL ═════════════════════════════════\n\nerror MulticallFailed();\n\n// contracts/libs/TypeCasts.sol\n\nlibrary TypeCasts {\n    // alignment preserving cast\n    function addressToBytes32(address addr) internal pure returns (bytes32) {\n        return bytes32(uint256(uint160(addr)));\n    }\n\n    // alignment preserving cast\n    function bytes32ToAddress(bytes32 buf) internal pure returns (address) {\n        return address(uint160(uint256(buf)));\n    }\n}\n\n// contracts/libs/stack/Number.sol\n\n/// Number is a compact representation of uint256, that is fit into 16 bits\n/// with the maximum relative error under 0.4%.\ntype Number is uint16;\n\nusing NumberLib for Number global;\n\n/// # Number\n/// Library for compact representation of uint256 numbers.\n/// - Number is stored using mantissa and exponent, each occupying 8 bits.\n/// - Numbers under 2**8 are stored as `mantissa` with `exponent = 0xFF`.\n/// - Numbers at least 2**8 are approximated as `(256 + mantissa) \u003c\u003c exponent`\n/// \u003e - `0 \u003c= mantissa \u003c 256`\n/// \u003e - `0 \u003c= exponent \u003c= 247` (`256 * 2**248` doesn't fit into uint256)\n/// # Number stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type  | Bytes |\n/// | ---------- | -------- | ----- | ----- |\n/// | (002..001] | mantissa | uint8 | 1     |\n/// | (001..000] | exponent | uint8 | 1     |\n\nlibrary NumberLib {\n    /// @dev Amount of bits to shift to mantissa field\n    uint16 private constant SHIFT_MANTISSA = 8;\n\n    /// @notice For bwad math (binary wad) we use 2**64 as \"wad\" unit.\n    /// @dev We are using not using 10**18 as wad, because it is not stored precisely in NumberLib.\n    uint256 internal constant BWAD_SHIFT = 64;\n    uint256 internal constant BWAD = 1 \u003c\u003c BWAD_SHIFT;\n    /// @notice ~0.1% in bwad units.\n    uint256 internal constant PER_MILLE_SHIFT = BWAD_SHIFT - 10;\n    uint256 internal constant PER_MILLE = 1 \u003c\u003c PER_MILLE_SHIFT;\n\n    /// @notice Compresses uint256 number into 16 bits.\n    function compress(uint256 value) internal pure returns (Number) {\n        // Find `msb` such as `2**msb \u003c= value \u003c 2**(msb + 1)`\n        uint256 msb = mostSignificantBit(value);\n        // We want to preserve 9 bits of precision.\n        // The highest bit is always 1, so we can skip it.\n        // The remaining 8 highest bits are stored as mantissa.\n        if (msb \u003c 8) {\n            // Value is less than 2**8, so we can use value as mantissa with \"-1\" exponent.\n            return _encode(uint8(value), 0xFF);\n        } else {\n            // We use `msb - 8` as exponent otherwise. Note that `exponent \u003e= 0`.\n            unchecked {\n                uint256 exponent = msb - 8;\n                // Shifting right by `msb-8` bits will shift the \"remaining 8 highest bits\" into the 8 lowest bits.\n                // uint8() will truncate the highest bit.\n                return _encode(uint8(value \u003e\u003e exponent), uint8(exponent));\n            }\n        }\n    }\n\n    /// @notice Decompresses 16 bits number into uint256.\n    /// @dev The outcome is an approximation of the original number: `(value - value / 256) \u003c number \u003c= value`.\n    function decompress(Number number) internal pure returns (uint256 value) {\n        // Isolate 8 highest bits as the mantissa.\n        uint256 mantissa = Number.unwrap(number) \u003e\u003e SHIFT_MANTISSA;\n        // This will truncate the highest bits, leaving only the exponent.\n        uint256 exponent = uint8(Number.unwrap(number));\n        if (exponent == 0xFF) {\n            return mantissa;\n        } else {\n            unchecked {\n                return (256 + mantissa) \u003c\u003c (exponent);\n            }\n        }\n    }\n\n    /// @dev Returns the most significant bit of `x`\n    /// https://solidity-by-example.org/bitwise/\n    function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\n        // To find `msb` we determine it bit by bit, starting from the highest one.\n        // `0 \u003c= msb \u003c= 255`, so we start from the highest bit, 1\u003c\u003c7 == 128.\n        // If `x` is at least 2**128, then the highest bit of `x` is at least 128.\n        // solhint-disable no-inline-assembly\n        assembly {\n            // `f` is set to 1\u003c\u003c7 if `x \u003e= 2**128` and to 0 otherwise.\n            let f := shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\n            // If `x \u003e= 2**128` then set `msb` highest bit to 1 and shift `x` right by 128.\n            // Otherwise, `msb` remains 0 and `x` remains unchanged.\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        // `x` is now at most 2**128 - 1. Continue the same way, the next highest bit is 1\u003c\u003c6 == 64.\n        assembly {\n            // `f` is set to 1\u003c\u003c6 if `x \u003e= 2**64` and to 0 otherwise.\n            let f := shl(6, gt(x, 0xFFFFFFFFFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c5 if `x \u003e= 2**32` and to 0 otherwise.\n            let f := shl(5, gt(x, 0xFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c4 if `x \u003e= 2**16` and to 0 otherwise.\n            let f := shl(4, gt(x, 0xFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c3 if `x \u003e= 2**8` and to 0 otherwise.\n            let f := shl(3, gt(x, 0xFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c2 if `x \u003e= 2**4` and to 0 otherwise.\n            let f := shl(2, gt(x, 0xF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c1 if `x \u003e= 2**2` and to 0 otherwise.\n            let f := shl(1, gt(x, 0x3))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1 if `x \u003e= 2**1` and to 0 otherwise.\n            let f := gt(x, 0x1)\n            msb := or(msb, f)\n        }\n    }\n\n    /// @dev Wraps (mantissa, exponent) pair into Number.\n    function _encode(uint8 mantissa, uint8 exponent) private pure returns (Number) {\n        // Casts below are upcasts, so they are safe.\n        return Number.wrap(uint16(mantissa) \u003c\u003c SHIFT_MANTISSA | uint16(exponent));\n    }\n}\n\n// contracts/libs/stack/Request.sol\n\n/// Request is encoded data with \"message execution request\".\ntype Request is uint192;\n\nusing RequestLib for Request global;\n\n/// Library for formatting _the request part_ of _the base messages_.\n/// - Request represents a message sender requirements for the message execution on the destination chain.\n/// - Request occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n/// \u003e gasDrop field is included for future compatibility and is ignored at the moment.\n///\n/// # Request stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type   | Bytes | Description                                          |\n/// | ---------- | -------- | ------ | ----- | ---------------------------------------------------- |\n/// | (024..012] | gasDrop  | uint96 | 12    | Minimum amount of gas token to drop to the recipient |\n/// | (012..004] | gasLimit | uint64 | 8     | Minimum amount of gas units to supply for execution  |\n/// | (004..000] | version  | uint32 | 4     | Base message version to pass to the recipient        |\n\nlibrary RequestLib {\n    /// @dev Amount of bits to shift to gasDrop field\n    uint192 private constant SHIFT_GAS_DROP = 12 * 8;\n    /// @dev Amount of bits to shift to gasLimit field\n    uint192 private constant SHIFT_GAS_LIMIT = 4 * 8;\n\n    /// @notice Returns an encoded request with the given fields\n    /// @param gasDrop_     Minimum amount of gas token to drop to the recipient (ignored at the moment)\n    /// @param gasLimit_    Minimum amount of gas units to supply for execution\n    /// @param version_     Base message version to pass to the recipient\n    function encodeRequest(uint96 gasDrop_, uint64 gasLimit_, uint32 version_) internal pure returns (Request) {\n        // Casts below are upcasts, so they are safe\n        return Request.wrap(uint192(gasDrop_) \u003c\u003c SHIFT_GAS_DROP | uint192(gasLimit_) \u003c\u003c SHIFT_GAS_LIMIT | version_);\n    }\n\n    /// @notice Wraps the padded encoded request into a Request-typed value.\n    /// @dev The \"padded\" request is simply an encoded request casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded requests\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedRequest) internal pure returns (Request) {\n        // Casting to uint192 will truncate the highest bits, which is the behavior we want\n        return Request.wrap(uint192(paddedRequest));\n    }\n\n    /// @notice Returns the requested of gas token to drop to the recipient.\n    function gasDrop(Request request) internal pure returns (uint96) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return uint96(Request.unwrap(request) \u003e\u003e SHIFT_GAS_DROP);\n    }\n\n    /// @notice Returns the requested minimum amount of gas units to supply for execution.\n    function gasLimit(Request request) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Request.unwrap(request) \u003e\u003e SHIFT_GAS_LIMIT);\n    }\n\n    /// @notice Returns the requested base message version to pass to the recipient.\n    function version(Request request) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Request.unwrap(request));\n    }\n}\n\n// node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        require(value \u003c= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        require(value \u003c= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        require(value \u003c= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value \u003c= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        require(value \u003c= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        require(value \u003c= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        require(value \u003c= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        require(value \u003c= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        require(value \u003c= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        require(value \u003c= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        require(value \u003c= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        require(value \u003c= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        require(value \u003c= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        require(value \u003c= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        require(value \u003c= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value \u003c= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        require(value \u003c= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        require(value \u003c= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        require(value \u003c= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value \u003c= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        require(value \u003c= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        require(value \u003c= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        require(value \u003c= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value \u003c= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        require(value \u003c= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        require(value \u003c= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        require(value \u003c= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value \u003c= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        require(value \u003c= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value \u003c= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value \u003c= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     *\n     * _Available since v3.0._\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value \u003e= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     *\n     * _Available since v3.0._\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value \u003c= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     *\n     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length \u003e 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance \u003e= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance \u003e= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length \u003e 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n\n// contracts/base/MultiCallable.sol\n\n/// @notice Collection of Multicall utilities. Fork of Multicall3:\n/// https://github.com/mds1/multicall/blob/master/src/Multicall3.sol\nabstract contract MultiCallable {\n    struct Call {\n        bool allowFailure;\n        bytes callData;\n    }\n\n    struct Result {\n        bool success;\n        bytes returnData;\n    }\n\n    /// @notice Aggregates a few calls to this contract into one multicall without modifying `msg.sender`.\n    function multicall(Call[] calldata calls) external returns (Result[] memory callResults) {\n        uint256 amount = calls.length;\n        callResults = new Result[](amount);\n        Call calldata call_;\n        for (uint256 i = 0; i \u003c amount;) {\n            call_ = calls[i];\n            Result memory result = callResults[i];\n            // We perform a delegate call to ourselves here. Delegate call does not modify `msg.sender`, so\n            // this will have the same effect as if `msg.sender` performed all the calls themselves one by one.\n            // solhint-disable-next-line avoid-low-level-calls\n            (result.success, result.returnData) = address(this).delegatecall(call_.callData);\n            // solhint-disable-next-line no-inline-assembly\n            assembly {\n                // Revert if the call fails and failure is not allowed\n                // `allowFailure := calldataload(call_)` and `success := mload(result)`\n                if iszero(or(calldataload(call_), mload(result))) {\n                    // Revert with `0x4d6a2328` (function selector for `MulticallFailed()`)\n                    mstore(0x00, 0x4d6a232800000000000000000000000000000000000000000000000000000000)\n                    revert(0x00, 0x04)\n                }\n            }\n            unchecked {\n                ++i;\n            }\n        }\n    }\n}\n\n// contracts/base/Version.sol\n\n/**\n * @title Versioned\n * @notice Version getter for contracts. Doesn't use any storage slots, meaning\n * it will never cause any troubles with the upgradeable contracts. For instance, this contract\n * can be added or removed from the inheritance chain without shifting the storage layout.\n */\nabstract contract Versioned {\n    /**\n     * @notice Struct that is mimicking the storage layout of a string with 32 bytes or less.\n     * Length is limited by 32, so the whole string payload takes two memory words:\n     * @param length    String length\n     * @param data      String characters\n     */\n    struct _ShortString {\n        uint256 length;\n        bytes32 data;\n    }\n\n    /// @dev Length of the \"version string\"\n    uint256 private immutable _length;\n    /// @dev Bytes representation of the \"version string\".\n    /// Strings with length over 32 are not supported!\n    bytes32 private immutable _data;\n\n    constructor(string memory version_) {\n        _length = bytes(version_).length;\n        if (_length \u003e 32) revert IncorrectVersionLength();\n        // bytes32 is left-aligned =\u003e this will store the byte representation of the string\n        // with the trailing zeroes to complete the 32-byte word\n        _data = bytes32(bytes(version_));\n    }\n\n    function version() external view returns (string memory versionString) {\n        // Load the immutable values to form the version string\n        _ShortString memory str = _ShortString(_length, _data);\n        // The only way to do this cast is doing some dirty assembly\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            versionString := str\n        }\n    }\n}\n\n// contracts/libs/ChainContext.sol\n\n/// @notice Library for accessing chain context variables as tightly packed integers.\n/// Messaging contracts should rely on this library for accessing chain context variables\n/// instead of doing the casting themselves.\nlibrary ChainContext {\n    using SafeCast for uint256;\n\n    /// @notice Returns the current block number as uint40.\n    /// @dev Reverts if block number is greater than 40 bits, which is not supposed to happen\n    /// until the block.timestamp overflows (assuming block time is at least 1 second).\n    function blockNumber() internal view returns (uint40) {\n        return block.number.toUint40();\n    }\n\n    /// @notice Returns the current block timestamp as uint40.\n    /// @dev Reverts if block timestamp is greater than 40 bits, which is\n    /// supposed to happen approximately in year 36835.\n    function blockTimestamp() internal view returns (uint40) {\n        return block.timestamp.toUint40();\n    }\n\n    /// @notice Returns the chain id as uint32.\n    /// @dev Reverts if chain id is greater than 32 bits, which is not\n    /// supposed to happen in production.\n    function chainId() internal view returns (uint32) {\n        return block.chainid.toUint32();\n    }\n}\n\n// contracts/libs/Structures.sol\n\n// Here we define common enums and structures to enable their easier reusing later.\n\n// ═══════════════════════════════ AGENT STATUS ════════════════════════════════\n\n/// @dev Potential statuses for the off-chain bonded agent:\n/// - Unknown: never provided a bond =\u003e signature not valid\n/// - Active: has a bond in BondingManager =\u003e signature valid\n/// - Unstaking: has a bond in BondingManager, initiated the unstaking =\u003e signature not valid\n/// - Resting: used to have a bond in BondingManager, successfully unstaked =\u003e signature not valid\n/// - Fraudulent: proven to commit fraud, value in Merkle Tree not updated =\u003e signature not valid\n/// - Slashed: proven to commit fraud, value in Merkle Tree was updated =\u003e signature not valid\n/// Unstaked agent could later be added back to THE SAME domain by staking a bond again.\n/// Honest agent: Unknown -\u003e Active -\u003e unstaking -\u003e Resting -\u003e Active ...\n/// Malicious agent: Unknown -\u003e Active -\u003e Fraudulent -\u003e Slashed\n/// Malicious agent: Unknown -\u003e Active -\u003e Unstaking -\u003e Fraudulent -\u003e Slashed\nenum AgentFlag {\n    Unknown,\n    Active,\n    Unstaking,\n    Resting,\n    Fraudulent,\n    Slashed\n}\n\n/// @notice Struct for storing an agent in the BondingManager contract.\nstruct AgentStatus {\n    AgentFlag flag;\n    uint32 domain;\n    uint32 index;\n}\n// 184 bits available for tight packing\n\nusing StructureUtils for AgentStatus global;\n\n/// @notice Potential statuses of an agent in terms of being in dispute\n/// - None: agent is not in dispute\n/// - Pending: agent is in unresolved dispute\n/// - Slashed: agent was in dispute that lead to agent being slashed\n/// Note: agent who won the dispute has their status reset to None\nenum DisputeFlag {\n    None,\n    Pending,\n    Slashed\n}\n\n/// @notice Struct for storing dispute status of an agent.\n/// @param flag         Dispute flag: None/Pending/Slashed.\n/// @param openedAt     Timestamp when the latest agent dispute was opened (zero if not opened).\n/// @param resolvedAt   Timestamp when the latest agent dispute was resolved (zero if not resolved).\nstruct DisputeStatus {\n    DisputeFlag flag;\n    uint40 openedAt;\n    uint40 resolvedAt;\n}\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\n/// @notice Struct representing the status of Destination contract.\n/// @param snapRootTime     Timestamp when latest snapshot root was accepted\n/// @param agentRootTime    Timestamp when latest agent root was accepted\n/// @param notaryIndex      Index of Notary who signed the latest agent root\nstruct DestinationStatus {\n    uint40 snapRootTime;\n    uint40 agentRootTime;\n    uint32 notaryIndex;\n}\n\n// ═══════════════════════════════ EXECUTION HUB ═══════════════════════════════\n\n/// @notice Potential statuses of the message in Execution Hub.\n/// - None: there hasn't been a valid attempt to execute the message yet\n/// - Failed: there was a valid attempt to execute the message, but recipient reverted\n/// - Success: there was a valid attempt to execute the message, and recipient did not revert\n/// Note: message can be executed until its status is Success\nenum MessageStatus {\n    None,\n    Failed,\n    Success\n}\n\nlibrary StructureUtils {\n    /// @notice Checks that Agent is Active\n    function verifyActive(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active) {\n            revert AgentNotActive();\n        }\n    }\n\n    /// @notice Checks that Agent is Unstaking\n    function verifyUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Unstaking) {\n            revert AgentNotUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Active or Unstaking\n    function verifyActiveUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active \u0026\u0026 status.flag != AgentFlag.Unstaking) {\n            revert AgentNotActiveNorUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Fraudulent\n    function verifyFraudulent(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Fraudulent) {\n            revert AgentNotFraudulent();\n        }\n    }\n\n    /// @notice Checks that Agent is not Unknown\n    function verifyKnown(AgentStatus memory status) internal pure {\n        if (status.flag == AgentFlag.Unknown) {\n            revert AgentUnknown();\n        }\n    }\n}\n\n// contracts/libs/memory/MemView.sol\n\n/// @dev MemView is an untyped view over a portion of memory to be used instead of `bytes memory`\ntype MemView is uint256;\n\n/// @dev Attach library functions to MemView\nusing MemViewLib for MemView global;\n\n/// @notice Library for operations with the memory views.\n/// Forked from https://github.com/summa-tx/memview-sol with several breaking changes:\n/// - The codebase is ported to Solidity 0.8\n/// - Custom errors are added\n/// - The runtime type checking is replaced with compile-time check provided by User-Defined Value Types\n///   https://docs.soliditylang.org/en/latest/types.html#user-defined-value-types\n/// - uint256 is used as the underlying type for the \"memory view\" instead of bytes29.\n///   It is wrapped into MemView custom type in order not to be confused with actual integers.\n/// - Therefore the \"type\" field is discarded, allowing to allocate 16 bytes for both view location and length\n/// - The documentation is expanded\n/// - Library functions unused by the rest of the codebase are removed\n//  - Very pretty code separators are added :)\nlibrary MemViewLib {\n    /// @notice Stack layout for uint256 (from highest bits to lowest)\n    /// (32 .. 16]      loc     16 bytes    Memory address of underlying bytes\n    /// (16 .. 00]      len     16 bytes    Length of underlying bytes\n\n    // ═══════════════════════════════════════════ BUILDING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Instantiate a new untyped memory view. This should generally not be called directly.\n     * Prefer `ref` wherever possible.\n     * @param loc_          The memory address\n     * @param len_          The length\n     * @return The new view with the specified location and length\n     */\n    function build(uint256 loc_, uint256 len_) internal pure returns (MemView) {\n        uint256 end_ = loc_ + len_;\n        // Make sure that a view is not constructed that points to unallocated memory\n        // as this could be indicative of a buffer overflow attack\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            if gt(end_, mload(0x40)) { end_ := 0 }\n        }\n        if (end_ == 0) {\n            revert UnallocatedMemory();\n        }\n        return _unsafeBuildUnchecked(loc_, len_);\n    }\n\n    /**\n     * @notice Instantiate a memory view from a byte array.\n     * @dev Note that due to Solidity memory representation, it is not possible to\n     * implement a deref, as the `bytes` type stores its len in memory.\n     * @param arr           The byte array\n     * @return The memory view over the provided byte array\n     */\n    function ref(bytes memory arr) internal pure returns (MemView) {\n        uint256 len_ = arr.length;\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 loc_;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // We add 0x20, so that the view starts exactly where the array data starts\n            loc_ := add(arr, 0x20)\n        }\n        return build(loc_, len_);\n    }\n\n    // ════════════════════════════════════════════ CLONING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to the new memory.\n     * @param memView       The memory view\n     * @return arr          The cloned byte array\n     */\n    function clone(MemView memView) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        unchecked {\n            _unsafeCopyTo(memView, ptr + 0x20);\n        }\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 len_ = memView.len();\n        uint256 footprint_ = memView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    /**\n     * @notice Copies all views, joins them into a new bytearray.\n     * @param memViews      The memory views\n     * @return arr          The new byte array with joined data behind the given views\n     */\n    function join(MemView[] memory memViews) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        MemView newView;\n        unchecked {\n            newView = _unsafeJoin(memViews, ptr + 0x20);\n        }\n        uint256 len_ = newView.len();\n        uint256 footprint_ = newView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    // ══════════════════════════════════════════ INSPECTING MEMORY VIEW ═══════════════════════════════════════════════\n\n    /**\n     * @notice Returns the memory address of the underlying bytes.\n     * @param memView       The memory view\n     * @return loc_         The memory address\n     */\n    function loc(MemView memView) internal pure returns (uint256 loc_) {\n        // loc is stored in the highest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u003e\u003e 128;\n    }\n\n    /**\n     * @notice Returns the number of bytes of the view.\n     * @param memView       The memory view\n     * @return len_         The length of the view\n     */\n    function len(MemView memView) internal pure returns (uint256 len_) {\n        // len is stored in the lowest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u0026 type(uint128).max;\n    }\n\n    /**\n     * @notice Returns the endpoint of `memView`.\n     * @param memView       The memory view\n     * @return end_         The endpoint of `memView`\n     */\n    function end(MemView memView) internal pure returns (uint256 end_) {\n        // The endpoint never overflows uint128, let alone uint256, so we could use unchecked math here\n        unchecked {\n            return memView.loc() + memView.len();\n        }\n    }\n\n    /**\n     * @notice Returns the number of memory words this memory view occupies, rounded up.\n     * @param memView       The memory view\n     * @return words_       The number of memory words\n     */\n    function words(MemView memView) internal pure returns (uint256 words_) {\n        // returning ceil(length / 32.0)\n        unchecked {\n            return (memView.len() + 31) \u003e\u003e 5;\n        }\n    }\n\n    /**\n     * @notice Returns the in-memory footprint of a fresh copy of the view.\n     * @param memView       The memory view\n     * @return footprint_   The in-memory footprint of a fresh copy of the view.\n     */\n    function footprint(MemView memView) internal pure returns (uint256 footprint_) {\n        // words() * 32\n        return memView.words() \u003c\u003c 5;\n    }\n\n    // ════════════════════════════════════════════ HASHING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the keccak256 hash of the underlying memory\n     * @param memView       The memory view\n     * @return digest       The keccak256 hash of the underlying memory\n     */\n    function keccak(MemView memView) internal pure returns (bytes32 digest) {\n        uint256 loc_ = memView.loc();\n        uint256 len_ = memView.len();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            digest := keccak256(loc_, len_)\n        }\n    }\n\n    /**\n     * @notice Adds a salt to the keccak256 hash of the underlying data and returns the keccak256 hash of the\n     * resulting data.\n     * @param memView       The memory view\n     * @return digestSalted keccak256(salt, keccak256(memView))\n     */\n    function keccakSalted(MemView memView, bytes32 salt) internal pure returns (bytes32 digestSalted) {\n        return keccak256(bytes.concat(salt, memView.keccak()));\n    }\n\n    // ════════════════════════════════════════════ SLICING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Safe slicing without memory modification.\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the given index\n     */\n    function slice(MemView memView, uint256 index_, uint256 len_) internal pure returns (MemView) {\n        uint256 loc_ = memView.loc();\n        // Ensure it doesn't overrun the view\n        if (loc_ + index_ + len_ \u003e memView.end()) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // loc_ + index_ \u003c= memView.end()\n            return build({loc_: loc_ + index_, len_: len_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing bytes from `index` to end(memView).\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @return The new view for the slice starting from the given index until the initial view endpoint\n     */\n    function sliceFrom(MemView memView, uint256 index_) internal pure returns (MemView) {\n        uint256 len_ = memView.len();\n        // Ensure it doesn't overrun the view\n        if (index_ \u003e len_) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // index_ \u003c= len_ =\u003e memView.loc() + index_ \u003c= memView.loc() + memView.len() == memView.end()\n            return build({loc_: memView.loc() + index_, len_: len_ - index_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the first `len` bytes.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the initial view beginning\n     */\n    function prefix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        return memView.slice({index_: 0, len_: len_});\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the last `len` byte.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length until the initial view endpoint\n     */\n    function postfix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        uint256 viewLen = memView.len();\n        // Ensure it doesn't overrun the view\n        if (len_ \u003e viewLen) {\n            revert ViewOverrun();\n        }\n        // Could do the unchecked math due to the check above\n        uint256 index_;\n        unchecked {\n            index_ = viewLen - len_;\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // len_ \u003c= memView.len() =\u003e memView.loc() \u003c= loc_ \u003c= memView.end()\n            return build({loc_: memView.loc() + viewLen - len_, len_: len_});\n        }\n    }\n\n    // ═══════════════════════════════════════════ INDEXING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Load up to 32 bytes from the view onto the stack.\n     * @dev Returns a bytes32 with only the `bytes_` HIGHEST bytes set.\n     * This can be immediately cast to a smaller fixed-length byte array.\n     * To automatically cast to an integer, use `indexUint`.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return result       The 32 byte result having only `bytes_` highest bytes set\n     */\n    function index(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (bytes32 result) {\n        if (bytes_ == 0) {\n            return bytes32(0);\n        }\n        // Can't load more than 32 bytes to the stack in one go\n        if (bytes_ \u003e 32) {\n            revert IndexedTooMuch();\n        }\n        // The last indexed byte should be within view boundaries\n        if (index_ + bytes_ \u003e memView.len()) {\n            revert ViewOverrun();\n        }\n        uint256 bitLength = bytes_ \u003c\u003c 3; // bytes_ * 8\n        uint256 loc_ = memView.loc();\n        // Get a mask with `bitLength` highest bits set\n        uint256 mask;\n        // 0x800...00 binary representation is 100...00\n        // sar stands for \"signed arithmetic shift\": https://en.wikipedia.org/wiki/Arithmetic_shift\n        // sar(N-1, 100...00) = 11...100..00, with exactly N highest bits set to 1\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            mask := sar(sub(bitLength, 1), 0x8000000000000000000000000000000000000000000000000000000000000000)\n        }\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load a full word using index offset, and apply mask to ignore non-relevant bytes\n            result := and(mload(add(loc_, index_)), mask)\n        }\n    }\n\n    /**\n     * @notice Parse an unsigned integer from the view at `index`.\n     * @dev Requires that the view have \u003e= `bytes_` bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return The unsigned integer\n     */\n    function indexUint(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (uint256) {\n        bytes32 indexedBytes = memView.index(index_, bytes_);\n        // `index()` returns left-aligned `bytes_`, while integers are right-aligned\n        // Shifting here to right-align with the full 32 bytes word: need to shift right `(32 - bytes_)` bytes\n        unchecked {\n            // memView.index() reverts when bytes_ \u003e 32, thus unchecked math\n            return uint256(indexedBytes) \u003e\u003e ((32 - bytes_) \u003c\u003c 3);\n        }\n    }\n\n    /**\n     * @notice Parse an address from the view at `index`.\n     * @dev Requires that the view have \u003e= 20 bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @return The address\n     */\n    function indexAddress(MemView memView, uint256 index_) internal pure returns (address) {\n        // index 20 bytes as `uint160`, and then cast to `address`\n        return address(uint160(memView.indexUint(index_, 20)));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns a memory view over the specified memory location\n    /// without checking if it points to unallocated memory.\n    function _unsafeBuildUnchecked(uint256 loc_, uint256 len_) private pure returns (MemView) {\n        // There is no scenario where loc or len would overflow uint128, so we omit this check.\n        // We use the highest 128 bits to encode the location and the lowest 128 bits to encode the length.\n        return MemView.wrap((loc_ \u003c\u003c 128) | len_);\n    }\n\n    /**\n     * @notice Copy the view to a location, return an unsafe memory reference\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memView       The memory view\n     * @param newLoc        The new location to copy the underlying view data\n     * @return The memory view over the unsafe memory with the copied underlying data\n     */\n    function _unsafeCopyTo(MemView memView, uint256 newLoc) private view returns (MemView) {\n        uint256 len_ = memView.len();\n        uint256 oldLoc = memView.loc();\n\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (newLoc \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        bool res;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // use the identity precompile (0x04) to copy\n            res := staticcall(gas(), 0x04, oldLoc, len_, newLoc, len_)\n        }\n        if (!res) revert PrecompileOutOfGas();\n        return _unsafeBuildUnchecked({loc_: newLoc, len_: len_});\n    }\n\n    /**\n     * @notice Join the views in memory, return an unsafe reference to the memory.\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memViews      The memory views\n     * @return The conjoined view pointing to the new memory\n     */\n    function _unsafeJoin(MemView[] memory memViews, uint256 location) private view returns (MemView) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (location \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        // Copy the views to the specified location one by one, by tracking the amount of copied bytes so far\n        uint256 offset = 0;\n        for (uint256 i = 0; i \u003c memViews.length;) {\n            MemView memView = memViews[i];\n            // We can use the unchecked math here as location + sum(view.length) will never overflow uint256\n            unchecked {\n                _unsafeCopyTo(memView, location + offset);\n                offset += memView.len();\n                ++i;\n            }\n        }\n        return _unsafeBuildUnchecked({loc_: location, len_: offset});\n    }\n}\n\n// contracts/libs/merkle/MerkleMath.sol\n\nlibrary MerkleMath {\n    // ═════════════════════════════════════════ BASIC MERKLE CALCULATIONS ═════════════════════════════════════════════\n\n    /**\n     * @notice Calculates the merkle root for the given leaf and merkle proof.\n     * @dev Will revert if proof length exceeds the tree height.\n     * @param index     Index of `leaf` in tree\n     * @param leaf      Leaf of the merkle tree\n     * @param proof     Proof of inclusion of `leaf` in the tree\n     * @param height    Height of the merkle tree\n     * @return root_    Calculated Merkle Root\n     */\n    function proofRoot(uint256 index, bytes32 leaf, bytes32[] memory proof, uint256 height)\n        internal\n        pure\n        returns (bytes32 root_)\n    {\n        // Proof length could not exceed the tree height\n        uint256 proofLen = proof.length;\n        if (proofLen \u003e height) revert TreeHeightTooLow();\n        root_ = leaf;\n        /// @dev Apply unchecked to all ++h operations\n        unchecked {\n            // Go up the tree levels from the leaf following the proof\n            for (uint256 h = 0; h \u003c proofLen; ++h) {\n                // Get a sibling node on current level: this is proof[h]\n                root_ = getParent(root_, proof[h], index, h);\n            }\n            // Go up to the root: the remaining siblings are EMPTY\n            for (uint256 h = proofLen; h \u003c height; ++h) {\n                root_ = getParent(root_, bytes32(0), index, h);\n            }\n        }\n    }\n\n    /**\n     * @notice Calculates the parent of a node on the path from one of the leafs to root.\n     * @param node          Node on a path from tree leaf to root\n     * @param sibling       Sibling for a given node\n     * @param leafIndex     Index of the tree leaf\n     * @param nodeHeight    \"Level height\" for `node` (ZERO for leafs, ORIGIN_TREE_HEIGHT for root)\n     */\n    function getParent(bytes32 node, bytes32 sibling, uint256 leafIndex, uint256 nodeHeight)\n        internal\n        pure\n        returns (bytes32 parent)\n    {\n        // Index for `node` on its \"tree level\" is (leafIndex / 2**height)\n        // \"Left child\" has even index, \"right child\" has odd index\n        if ((leafIndex \u003e\u003e nodeHeight) \u0026 1 == 0) {\n            // Left child\n            return getParent(node, sibling);\n        } else {\n            // Right child\n            return getParent(sibling, node);\n        }\n    }\n\n    /// @notice Calculates the parent of tow nodes in the merkle tree.\n    /// @dev We use implementation with H(0,0) = 0\n    /// This makes EVERY empty node in the tree equal to ZERO,\n    /// saving us from storing H(0,0), H(H(0,0), H(0, 0)), and so on\n    /// @param leftChild    Left child of the calculated node\n    /// @param rightChild   Right child of the calculated node\n    /// @return parent      Value for the node having above mentioned children\n    function getParent(bytes32 leftChild, bytes32 rightChild) internal pure returns (bytes32 parent) {\n        if (leftChild == bytes32(0) \u0026\u0026 rightChild == bytes32(0)) {\n            return 0;\n        } else {\n            return keccak256(bytes.concat(leftChild, rightChild));\n        }\n    }\n\n    // ════════════════════════════════ ROOT/PROOF CALCULATION FOR A LIST OF LEAFS ═════════════════════════════════════\n\n    /**\n     * @notice Calculates merkle root for a list of given leafs.\n     * Merkle Tree is constructed by padding the list with ZERO values for leafs until list length is `2**height`.\n     * Merkle Root is calculated for the constructed tree, and then saved in `leafs[0]`.\n     * \u003e Note:\n     * \u003e - `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * \u003e - Caller is expected not to reuse `hashes` list after the call, and only use `leafs[0]` value,\n     * which is guaranteed to contain the calculated merkle root.\n     * \u003e - root is calculated using the `H(0,0) = 0` Merkle Tree implementation. See MerkleTree.sol for details.\n     * @dev Amount of leaves should be at most `2**height`\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param height    Height of the Merkle Tree to construct\n     */\n    function calculateRoot(bytes32[] memory hashes, uint256 height) internal pure {\n        uint256 levelLength = hashes.length;\n        // Amount of hashes could not exceed amount of leafs in tree with the given height\n        if (levelLength \u003e (1 \u003c\u003c height)) revert TreeHeightTooLow();\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\": the amount of iterations for the for loop above.\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n            }\n        }\n    }\n\n    /**\n     * @notice Generates a proof of inclusion of a leaf in the list. If the requested index is outside\n     * of the list range, generates a proof of inclusion for an empty leaf (proof of non-inclusion).\n     * The Merkle Tree is constructed by padding the list with ZERO values until list length is a power of two\n     * __AND__ index is in the extended list range. For example:\n     *  - `hashes.length == 6` and `0 \u003c= index \u003c= 7` will \"extend\" the list to 8 entries.\n     *  - `hashes.length == 6` and `7 \u003c index \u003c= 15` will \"extend\" the list to 16 entries.\n     * \u003e Note: `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * Caller is expected not to reuse `hashes` list after the call.\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param index     Leaf index to generate the proof for\n     * @return proof    Generated merkle proof\n     */\n    function calculateProof(bytes32[] memory hashes, uint256 index) internal pure returns (bytes32[] memory proof) {\n        // Use only meaningful values for the shortened proof\n        // Check if index is within the list range (we want to generates proofs for outside leafs as well)\n        uint256 height = getHeight(index \u003c hashes.length ? hashes.length : (index + 1));\n        proof = new bytes32[](height);\n        uint256 levelLength = hashes.length;\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Use sibling for the merkle proof; `index^1` is index of our sibling\n                proof[h] = (index ^ 1 \u003c levelLength) ? hashes[index ^ 1] : bytes32(0);\n\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\"\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n                // Traverse to parent node\n                index \u003e\u003e= 1;\n            }\n        }\n    }\n\n    /// @notice Returns the height of the tree having a given amount of leafs.\n    function getHeight(uint256 leafs) internal pure returns (uint256 height) {\n        uint256 amount = 1;\n        while (amount \u003c leafs) {\n            unchecked {\n                ++height;\n            }\n            amount \u003c\u003c= 1;\n        }\n    }\n}\n\n// contracts/libs/stack/GasData.sol\n\n/// GasData in encoded data with \"basic information about gas prices\" for some chain.\ntype GasData is uint96;\n\nusing GasDataLib for GasData global;\n\n/// ChainGas is encoded data with given chain's \"basic information about gas prices\".\ntype ChainGas is uint128;\n\nusing GasDataLib for ChainGas global;\n\n/// Library for encoding and decoding GasData and ChainGas structs.\n/// # GasData\n/// `GasData` is a struct to store the \"basic information about gas prices\", that could\n/// be later used to approximate the cost of a message execution, and thus derive the\n/// minimal tip values for sending a message to the chain.\n/// \u003e - `GasData` is supposed to be cached by `GasOracle` contract, allowing to store the\n/// \u003e approximates instead of the exact values, and thus save on storage costs.\n/// \u003e - For instance, if `GasOracle` only updates the values on +- 10% change, having an\n/// \u003e 0.4% error on the approximates would be acceptable.\n/// `GasData` is supposed to be included in the Origin's state, which are synced across\n/// chains using Agent-signed snapshots and attestations.\n/// ## GasData stack layout (from highest bits to lowest)\n///\n/// | Position   | Field        | Type   | Bytes | Description                                         |\n/// | ---------- | ------------ | ------ | ----- | --------------------------------------------------- |\n/// | (012..010] | gasPrice     | uint16 | 2     | Gas price for the chain (in Wei per gas unit)       |\n/// | (010..008] | dataPrice    | uint16 | 2     | Calldata price (in Wei per byte of content)         |\n/// | (008..006] | execBuffer   | uint16 | 2     | Tx fee safety buffer for message execution (in Wei) |\n/// | (006..004] | amortAttCost | uint16 | 2     | Amortized cost for attestation submission (in Wei)  |\n/// | (004..002] | etherPrice   | uint16 | 2     | Chain's Ether Price / Mainnet Ether Price (in BWAD) |\n/// | (002..000] | markup       | uint16 | 2     | Markup for the message execution (in BWAD)          |\n/// \u003e See Number.sol for more details on `Number` type and BWAD (binary WAD) math.\n///\n/// ## ChainGas stack layout (from highest bits to lowest)\n///\n/// | Position   | Field   | Type   | Bytes | Description      |\n/// | ---------- | ------- | ------ | ----- | ---------------- |\n/// | (016..004] | gasData | uint96 | 12    | Chain's gas data |\n/// | (004..000] | domain  | uint32 | 4     | Chain's domain   |\nlibrary GasDataLib {\n    /// @dev Amount of bits to shift to gasPrice field\n    uint96 private constant SHIFT_GAS_PRICE = 10 * 8;\n    /// @dev Amount of bits to shift to dataPrice field\n    uint96 private constant SHIFT_DATA_PRICE = 8 * 8;\n    /// @dev Amount of bits to shift to execBuffer field\n    uint96 private constant SHIFT_EXEC_BUFFER = 6 * 8;\n    /// @dev Amount of bits to shift to amortAttCost field\n    uint96 private constant SHIFT_AMORT_ATT_COST = 4 * 8;\n    /// @dev Amount of bits to shift to etherPrice field\n    uint96 private constant SHIFT_ETHER_PRICE = 2 * 8;\n\n    /// @dev Amount of bits to shift to gasData field\n    uint128 private constant SHIFT_GAS_DATA = 4 * 8;\n\n    // ═════════════════════════════════════════════════ GAS DATA ══════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded GasData struct with the given fields.\n    /// @param gasPrice_        Gas price for the chain (in Wei per gas unit)\n    /// @param dataPrice_       Calldata price (in Wei per byte of content)\n    /// @param execBuffer_      Tx fee safety buffer for message execution (in Wei)\n    /// @param amortAttCost_    Amortized cost for attestation submission (in Wei)\n    /// @param etherPrice_      Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n    /// @param markup_          Markup for the message execution (in BWAD)\n    function encodeGasData(\n        Number gasPrice_,\n        Number dataPrice_,\n        Number execBuffer_,\n        Number amortAttCost_,\n        Number etherPrice_,\n        Number markup_\n    ) internal pure returns (GasData) {\n        // Number type wraps uint16, so could safely be casted to uint96\n        // forgefmt: disable-next-item\n        return GasData.wrap(\n            uint96(Number.unwrap(gasPrice_)) \u003c\u003c SHIFT_GAS_PRICE |\n            uint96(Number.unwrap(dataPrice_)) \u003c\u003c SHIFT_DATA_PRICE |\n            uint96(Number.unwrap(execBuffer_)) \u003c\u003c SHIFT_EXEC_BUFFER |\n            uint96(Number.unwrap(amortAttCost_)) \u003c\u003c SHIFT_AMORT_ATT_COST |\n            uint96(Number.unwrap(etherPrice_)) \u003c\u003c SHIFT_ETHER_PRICE |\n            uint96(Number.unwrap(markup_))\n        );\n    }\n\n    /// @notice Wraps padded uint256 value into GasData struct.\n    function wrapGasData(uint256 paddedGasData) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(paddedGasData));\n    }\n\n    /// @notice Returns the gas price, in Wei per gas unit.\n    function gasPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_GAS_PRICE));\n    }\n\n    /// @notice Returns the calldata price, in Wei per byte of content.\n    function dataPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_DATA_PRICE));\n    }\n\n    /// @notice Returns the tx fee safety buffer for message execution, in Wei.\n    function execBuffer(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_EXEC_BUFFER));\n    }\n\n    /// @notice Returns the amortized cost for attestation submission, in Wei.\n    function amortAttCost(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_AMORT_ATT_COST));\n    }\n\n    /// @notice Returns the ratio of Chain's Ether Price / Mainnet Ether Price, in BWAD math.\n    function etherPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_ETHER_PRICE));\n    }\n\n    /// @notice Returns the markup for the message execution, in BWAD math.\n    function markup(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data)));\n    }\n\n    // ════════════════════════════════════════════════ CHAIN DATA ═════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded ChainGas struct with the given fields.\n    /// @param gasData_ Chain's gas data\n    /// @param domain_  Chain's domain\n    function encodeChainGas(GasData gasData_, uint32 domain_) internal pure returns (ChainGas) {\n        // GasData type wraps uint96, so could safely be casted to uint128\n        return ChainGas.wrap(uint128(GasData.unwrap(gasData_)) \u003c\u003c SHIFT_GAS_DATA | uint128(domain_));\n    }\n\n    /// @notice Wraps padded uint256 value into ChainGas struct.\n    function wrapChainGas(uint256 paddedChainGas) internal pure returns (ChainGas) {\n        // Casting to uint128 will truncate the highest bits, which is the behavior we want\n        return ChainGas.wrap(uint128(paddedChainGas));\n    }\n\n    /// @notice Returns the chain's gas data.\n    function gasData(ChainGas data) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(ChainGas.unwrap(data) \u003e\u003e SHIFT_GAS_DATA));\n    }\n\n    /// @notice Returns the chain's domain.\n    function domain(ChainGas data) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(ChainGas.unwrap(data));\n    }\n\n    /// @notice Returns the hash for the list of ChainGas structs.\n    function snapGasHash(ChainGas[] memory snapGas) internal pure returns (bytes32 snapGasHash_) {\n        // Use assembly to calculate the hash of the array without copying it\n        // ChainGas takes a single word of storage, thus ChainGas[] is stored in the following way:\n        // 0x00: length of the array, in words\n        // 0x20: first ChainGas struct\n        // 0x40: second ChainGas struct\n        // And so on...\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Find the location where the array data starts, we add 0x20 to skip the length field\n            let loc := add(snapGas, 0x20)\n            // Load the length of the array (in words).\n            // Shifting left 5 bits is equivalent to multiplying by 32: this converts from words to bytes.\n            let len := shl(5, mload(snapGas))\n            // Calculate the hash of the array\n            snapGasHash_ := keccak256(loc, len)\n        }\n    }\n}\n\n// contracts/libs/stack/Header.sol\n\n/// Header is encoded data with \"general routing information\".\ntype Header is uint136;\n\nusing HeaderLib for Header global;\n\n/// Types of messages supported by Origin-Destination\n/// - Base: message sent by protocol user, contains tips\n/// - Manager: message sent between AgentManager contracts located on different chains, no tips\nenum MessageFlag {\n    Base,\n    Manager\n}\n\nusing HeaderLib for MessageFlag global;\n\n/// Library for formatting _the header part_ of _the messages used by Origin and Destination_.\n/// - Header represents general information for routing a Message for Origin and Destination.\n/// - Header occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n///\n/// # Header stack layout (from highest bits to lowest)\n///\n/// | Position   | Field            | Type   | Bytes | Description                             |\n/// | ---------- | ---------------- | ------ | ----- | --------------------------------------- |\n/// | (017..016] | flag             | uint8  | 1     | Flag specifying the type of message     |\n/// | (016..012] | origin           | uint32 | 4     | Domain where message originated         |\n/// | (012..008] | nonce            | uint32 | 4     | Message nonce on the origin domain      |\n/// | (008..004] | destination      | uint32 | 4     | Domain where message will be executed   |\n/// | (004..000] | optimisticPeriod | uint32 | 4     | Optimistic period that will be enforced |\nlibrary HeaderLib {\n    /// @dev Amount of bits to shift to flag field\n    uint136 private constant SHIFT_FLAG = 16 * 8;\n    /// @dev Amount of bits to shift to origin field\n    uint136 private constant SHIFT_ORIGIN = 12 * 8;\n    /// @dev Amount of bits to shift to nonce field\n    uint136 private constant SHIFT_NONCE = 8 * 8;\n    /// @dev Amount of bits to shift to destination field\n    uint136 private constant SHIFT_DESTINATION = 4 * 8;\n\n    /// @notice Returns an encoded header with provided fields\n    /// @param origin_              Domain of origin chain\n    /// @param nonce_               Message nonce on origin chain\n    /// @param destination_         Domain of destination chain\n    /// @param optimisticPeriod_    Optimistic period for message execution\n    function encodeHeader(\n        MessageFlag flag_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint32 destination_,\n        uint32 optimisticPeriod_\n    ) internal pure returns (Header) {\n        // All casts below are upcasts, so they are safe\n        // forgefmt: disable-next-item\n        return Header.wrap(\n            uint136(uint8(flag_)) \u003c\u003c SHIFT_FLAG |\n            uint136(origin_) \u003c\u003c SHIFT_ORIGIN |\n            uint136(nonce_) \u003c\u003c SHIFT_NONCE |\n            uint136(destination_) \u003c\u003c SHIFT_DESTINATION |\n            uint136(optimisticPeriod_)\n        );\n    }\n\n    /// @notice Checks that the header is a valid encoded header.\n    function isHeader(uint256 paddedHeader) internal pure returns (bool) {\n        // Check that flag is within range\n        return _flag(paddedHeader) \u003c= uint8(type(MessageFlag).max);\n    }\n\n    /// @notice Wraps the padded encoded request into a Header-typed value.\n    /// @dev The \"padded\" header is simply an encoded header casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded headers\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedHeader) internal pure returns (Header) {\n        // Check that flag is within range\n        if (!isHeader(paddedHeader)) revert FlagOutOfRange();\n        // Casting to uint136 will truncate the highest bits, which is the behavior we want\n        return Header.wrap(uint136(paddedHeader));\n    }\n\n    /// @notice Returns header's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Header header) internal pure returns (bytes32 hashedHeader) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store header in scratch space\n            mstore(0, header)\n            // Compute hash of header padded to 32 bytes\n            hashedHeader := keccak256(0, 32)\n        }\n    }\n\n    // ══════════════════════════════════════════════ HEADER SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns header's flag field\n    function flag(Header header) internal pure returns (MessageFlag) {\n        // We check that flag is within range when wrapping the header, so this cast is safe\n        return MessageFlag(_flag(Header.unwrap(header)));\n    }\n\n    /// @notice Returns header's origin field\n    function origin(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_ORIGIN);\n    }\n\n    /// @notice Returns header's nonce field\n    function nonce(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_NONCE);\n    }\n\n    /// @notice Returns header's destination field\n    function destination(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_DESTINATION);\n    }\n\n    /// @notice Returns header's optimistic seconds field\n    function optimisticPeriod(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns header's flag field without casting to MessageFlag\n    function _flag(uint256 paddedHeader) private pure returns (uint8) {\n        // Casting to uint8 will truncate the highest bits, which is the behavior we want\n        return uint8(paddedHeader \u003e\u003e SHIFT_FLAG);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n     * constructor.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall \u0026\u0026 _initialized \u003c 1) || (!AddressUpgradeable.isContract(address(this)) \u0026\u0026 _initialized == 1),\n            \"Initializable: contract is already initialized\"\n        );\n        _initialized = 1;\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: setting the version to 255 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing \u0026\u0026 _initialized \u003c version, \"Initializable: contract is already initialized\");\n        _initialized = version;\n        _initializing = true;\n        _;\n        _initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        require(_initializing, \"Initializable: contract is not initializing\");\n        _;\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized != type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint8) {\n        return _initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _initializing;\n    }\n}\n\n// contracts/interfaces/IAgentManager.sol\n\ninterface IAgentManager {\n    /**\n     * @notice Allows Inbox to open a Dispute between a Guard and a Notary, if they are both not in Dispute already.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Guard or Notary is already in Dispute.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Allows Inbox to slash an agent, if their fraud was proven.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Domain doesn't match the saved agent domain.\n     * @param domain    Domain where the Agent is active\n     * @param agent     Address of the Agent\n     * @param prover    Address that initially provided fraud proof\n     */\n    function slashAgent(uint32 domain, address agent, address prover) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest known root of the Agent Merkle Tree.\n     */\n    function agentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns the number of opened Disputes.\n     * @dev This includes the Disputes that have been resolved already.\n     */\n    function getDisputesAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns information about the dispute with the given index.\n     * @dev Will revert if dispute with given index hasn't been opened yet.\n     * @param index             Dispute index\n     * @return guard            Address of the Guard in the Dispute\n     * @return notary           Address of the Notary in the Dispute\n     * @return slashedAgent     Address of the Agent who was slashed when Dispute was resolved\n     * @return fraudProver      Address who provided fraud proof to resolve the Dispute\n     * @return reportPayload    Raw payload with report data that led to the Dispute\n     * @return reportSignature  Guard signature for the report payload\n     */\n    function getDispute(uint256 index)\n        external\n        view\n        returns (\n            address guard,\n            address notary,\n            address slashedAgent,\n            address fraudProver,\n            bytes memory reportPayload,\n            bytes memory reportSignature\n        );\n\n    /**\n     * @notice Returns the current Dispute status of a given agent. See Structures.sol for details.\n     * @dev Every returned value will be set to zero if agent was not slashed and is not in Dispute.\n     * `rival` and `disputePtr` will be set to zero if the agent was slashed without being in Dispute.\n     * @param agent         Agent address\n     * @return flag         Flag describing the current Dispute status for the agent: None/Pending/Slashed\n     * @return rival        Address of the rival agent in the Dispute\n     * @return fraudProver  Address who provided fraud proof to resolve the Dispute\n     * @return disputePtr   Index of the opened Dispute PLUS ONE. Zero if agent is not in Dispute.\n     */\n    function disputeStatus(address agent)\n        external\n        view\n        returns (DisputeFlag flag, address rival, address fraudProver, uint256 disputePtr);\n}\n\n// contracts/interfaces/IAgentSecured.sol\n\ninterface IAgentSecured {\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * between a Guard and a Notary has been opened.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * has been resolved due to one of the agents being slashed.\n     * \u003e `rivalIndex` will be ZERO, if the slashed agent was not in the Dispute.\n     * @param slashedIndex  Index of the slashed agent in the Agent Merkle Tree\n     * @param rivalIndex    Index of the their Dispute Rival in the Agent Merkle Tree\n     */\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the address of the local AgentManager contract, which is treated as\n     * the \"source of truth\" for agent statuses.\n     */\n    function agentManager() external view returns (address);\n\n    /**\n     * @notice Returns the address of the local Inbox contract, which is treated as\n     * the \"source of truth\" for agent-signed statements.\n     * @dev Inbox passes verified agent statements to `IAgentSecured` contract.\n     */\n    function inbox() external view returns (address);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns (flag, openedAt, resolvedAt) that describes the latest status of\n     * the latest dispute for an agent with a given index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param agentIndex    Agent index in the Agent Merkle Tree\n     * @return              Latest dispute status for the given agent: (flag, openedAt, resolvedAt)\n     */\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory);\n}\n\n// contracts/libs/memory/ByteString.sol\n\n/// @dev CallData is a memory view over the payload to be used for an external call, i.e.\n/// recipient.call(callData). Its length is always (4 + 32 * N) bytes:\n/// - First 4 bytes represent the function selector.\n/// - 32 * N bytes represent N words that function arguments occupy.\ntype CallData is uint256;\n\n/// @dev Attach library functions to CallData\nusing ByteString for CallData global;\n\n/// @dev Signature is a memory view over a \"65 bytes\" array representing a ECDSA signature.\ntype Signature is uint256;\n\n/// @dev Attach library functions to Signature\nusing ByteString for Signature global;\n\nlibrary ByteString {\n    using MemViewLib for bytes;\n\n    /**\n     * @dev non-compact ECDSA signatures are enforced as of OZ 4.7.3\n     *\n     *      Signature payload memory layout\n     * [000 .. 032) r   bytes32 32 bytes\n     * [032 .. 064) s   bytes32 32 bytes\n     * [064 .. 065) v   uint8    1 byte\n     */\n    uint256 internal constant SIGNATURE_LENGTH = 65;\n    uint256 private constant OFFSET_R = 0;\n    uint256 private constant OFFSET_S = 32;\n    uint256 private constant OFFSET_V = 64;\n\n    /**\n     * @dev Calldata memory layout\n     * [000 .. 004) selector    bytes4  4 bytes\n     *      Optional: N function arguments\n     * [004 .. 036) arg1        bytes32 32 bytes\n     *      ..\n     * [AAA .. END) argN        bytes32 32 bytes\n     */\n    uint256 internal constant SELECTOR_LENGTH = 4;\n    uint256 private constant OFFSET_SELECTOR = 0;\n    uint256 private constant OFFSET_ARGUMENTS = SELECTOR_LENGTH;\n\n    // ═════════════════════════════════════════════════ SIGNATURE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the signature payload from the given values.\n     * @dev Using ByteString.formatSignature({r: r, s: s, v: v}) will make sure\n     * that params are given in the right order.\n     */\n    function formatSignature(bytes32 r, bytes32 s, uint8 v) internal pure returns (bytes memory) {\n        return abi.encodePacked(r, s, v);\n    }\n\n    /**\n     * @notice Returns a Signature view over for the given payload.\n     * @dev Will revert if the payload is not a signature.\n     */\n    function castToSignature(bytes memory payload) internal pure returns (Signature) {\n        return castToSignature(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Signature view.\n     * @dev Will revert if the memory view is not over a signature.\n     */\n    function castToSignature(MemView memView) internal pure returns (Signature) {\n        if (!isSignature(memView)) revert UnformattedSignature();\n        return Signature.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a signature\n     */\n    function isSignature(MemView memView) internal pure returns (bool) {\n        return memView.len() == SIGNATURE_LENGTH;\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Signature signature) internal pure returns (MemView) {\n        return MemView.wrap(Signature.unwrap(signature));\n    }\n\n    // ═════════════════════════════════════════════ SIGNATURE SLICING ═════════════════════════════════════════════════\n\n    /// @notice Unpacks signature payload into (r, s, v) parameters.\n    /// @dev Make sure to verify signature length with isSignature() beforehand.\n    function toRSV(Signature signature) internal pure returns (bytes32 r, bytes32 s, uint8 v) {\n        // Get the underlying memory view\n        MemView memView = unwrap(signature);\n        r = memView.index({index_: OFFSET_R, bytes_: 32});\n        s = memView.index({index_: OFFSET_S, bytes_: 32});\n        // Can be safely casted to uint8, since we index a single byte\n        v = uint8(memView.indexUint({index_: OFFSET_V, bytes_: 1}));\n    }\n\n    // ═════════════════════════════════════════════════ CALLDATA ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the calldata with the modified arguments:\n     * the existing arguments are prepended with the arguments from the prefix.\n     * @dev Given:\n     *  - `calldata = abi.encodeWithSelector(foo.selector, d, e);`\n     *  - `prefix = abi.encode(a, b, c);`\n     *  - `a`, `b`, `c` are arguments of static type (i.e. not dynamically sized ones)\n     *      Then:\n     *  - Function will return abi.encodeWithSelector(foo.selector, a, c, c, d, e)\n     *  - Returned calldata will trigger `foo(a, b, c, d, e)` when used for a contract call.\n     * Note: for clarification as to what types are considered static, see\n     * https://docs.soliditylang.org/en/latest/abi-spec.html#formal-specification-of-the-encoding\n     * @param callData  Calldata that needs to be modified\n     * @param prefix    ABI-encoded arguments to use as the first arguments in the new calldata\n     * @return Modified calldata having prefix as the first arguments.\n     */\n    function addPrefix(CallData callData, bytes memory prefix) internal view returns (bytes memory) {\n        // Prefix should occupy a whole amount of words in memory\n        if (!_fullWords(prefix.length)) revert UnformattedCallDataPrefix();\n        MemView[] memory views = new MemView[](3);\n        // Use payload's function selector\n        views[0] = abi.encodePacked(callData.callSelector()).ref();\n        // Use prefix as the first arguments\n        views[1] = prefix.ref();\n        // Use payload's remaining arguments\n        views[2] = callData.arguments();\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a CallData view over for the given payload.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(bytes memory payload) internal pure returns (CallData) {\n        return castToCallData(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a CallData view.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(MemView memView) internal pure returns (CallData) {\n        if (!isCallData(memView)) revert UnformattedCallData();\n        return CallData.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a valid calldata, i.e.\n     * a function selector, followed by arbitrary amount of arguments.\n     */\n    function isCallData(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Calldata should at least have a function selector\n        if (length \u003c SELECTOR_LENGTH) return false;\n        // The remainder of the calldata should be exactly N memory words (N \u003e= 0)\n        return _fullWords(length - SELECTOR_LENGTH);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(CallData callData) internal pure returns (MemView) {\n        return MemView.wrap(CallData.unwrap(callData));\n    }\n\n    /// @notice Returns callData's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(CallData callData) internal pure returns (bytes32) {\n        return callData.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ CALLDATA SLICING ══════════════════════════════════════════════════\n\n    /**\n     * @notice Returns amount of memory words (32 byte chunks) the function arguments\n     * occupy in the calldata.\n     * @dev This might differ from amount of arguments supplied, if any of the arguments\n     * occupies more than one memory slot. It is true, however, that argument part of the payload\n     * occupies exactly N words, even for dynamic types like `bytes`\n     */\n    function argumentWords(CallData callData) internal pure returns (uint256) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        // Equivalent of (length - SELECTOR_LENGTH) / 32\n        return (memView.len() - SELECTOR_LENGTH) \u003e\u003e 5;\n    }\n\n    /// @notice Returns selector for the provided calldata.\n    function callSelector(CallData callData) internal pure returns (bytes4) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return bytes4(memView.index({index_: OFFSET_SELECTOR, bytes_: SELECTOR_LENGTH}));\n    }\n\n    /// @notice Returns abi encoded arguments for the provided calldata.\n    function arguments(CallData callData) internal pure returns (MemView) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return memView.sliceFrom({index_: OFFSET_ARGUMENTS});\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if length is full amount of memory words (32 bytes).\n    function _fullWords(uint256 length) internal pure returns (bool) {\n        // The equivalent of length % 32 == 0\n        return length \u0026 31 == 0;\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n    function __Context_init() internal onlyInitializing {\n    }\n\n    function __Context_init_unchained() internal onlyInitializing {\n    }\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[50] private __gap;\n}\n\n// contracts/libs/merkle/MerkleTree.sol\n\n/// `BaseTree` is a struct representing incremental merkle tree.\n/// - Contains only the current branch.\n/// - The number of inserted leaves is stored externally, and is later supplied for tree operations.\n/// - Has a fixed height of `ORIGIN_TREE_HEIGHT`.\n/// - Can store up to `2 ** ORIGIN_TREE_HEIGHT - 1` leaves.\n/// \u003e Note: the hash function for the tree `H(x, y)` is defined as:\n/// \u003e - `H(0,0) = 0`\n/// \u003e - `H(x,y) = keccak256(x, y), when (x != 0 || y != 0)`\n/// ## Invariant for leafs\n/// - The leftmost empty leaf has `index == count`, where `count` is the amount of the inserted leafs so far.\n/// - Value for any empty leaf or node is bytes32(0).\n/// ## Invariant for current branch\n/// `branch[i]` is always the value of a node on the i-th level.\n/// Levels are numbered from leafs to root: `0 .. ORIGIN_TREE_HEIGHT`.\n/// `branch[i]` stores the value for the node, such that:\n//  - The node is a \"left child\" (e.g. has an even index).\n/// - The node must have two non-empty children.\n/// - Out of all level's \"left child\" nodes with \"non-empty children\",\n/// the one with the biggest index (the rightmost one) is stored as `branch[i]`.\n/// \u003e __`branch` could be used to form a proof of inclusion for the first empty leaf (`index == count`).__\n/// _Here is how:_\n/// - Let's walk along the path from the \"first empty leaf\" to the root.\n/// - i-th bit of the \"first empty leaf\" index (which is equal to `count`) determines if the path's node\n/// for this i-th level is a \"left child\" or a \"right child\".\n/// - i-th bit in `count` is 0 → we are the left child on this level → sibling is the right child\n/// that does not exist yet → `proof[i] = bytes32(0)`.\n/// - i-th bit in `count` is 1 → we are the right child on this level → sibling is the left child\n/// sibling is the rightmost \"left child\" node on the level → `proof[i] = branch[i]`.\n/// \u003e Therefore `proof[i] = (count \u0026 (1 \u003c\u003c i)) == 0 ? bytes32(0) : branch[i])`\nstruct BaseTree {\n    bytes32[ORIGIN_TREE_HEIGHT] branch;\n}\n\nusing MerkleTree for BaseTree global;\n\n/// `HistoricalTree` is an incremental merkle tree keeping track of its historical merkle roots.\n/// \u003e - `roots[N]` is the root of the tree after `N` leafs were inserted\n/// \u003e - `roots[0] == bytes32(0)`\n/// @param tree     Incremental merkle tree\n/// @param roots    Historical merkle roots of the tree\nstruct HistoricalTree {\n    BaseTree tree;\n    bytes32[] roots;\n}\n\nusing MerkleTree for HistoricalTree global;\n\n/// `DynamicTree` is a struct representing a Merkle Tree with `2**AGENT_TREE_HEIGHT` leaves.\n/// - A single operation is available: update value for leaf with an arbitrary index (which might be a non-empty leaf).\n/// - This is done by requesting the proof of inclusion for the old value, which is used to both\n/// verify the old value, and calculate the new root.\n/// \u003e Based on Original idea from [ER forum post](https://ethresear.ch/t/efficient-on-chain-dynamic-merkle-tree/11054).\nstruct DynamicTree {\n    bytes32 root;\n}\n\nusing MerkleTree for DynamicTree global;\n\n/// MerkleTree is work based on Nomad's Merkle.sol, which is used under MIT OR Apache-2.0\n/// [link](https://github.com/nomad-xyz/monorepo/blob/main/packages/contracts-core/contracts/libs/Merkle.sol).\n/// With the following changes:\n/// - Adapted for Solidity 0.8.x.\n/// - Amount of tree leaves stored externally.\n/// - Added thorough documentation.\n/// - `H(0,0) = 0` optimization from [ER forum post](https://ethresear.ch/t/optimizing-sparse-merkle-trees/3751/6).\n/// \u003e Nomad's Merkle.sol is work based on eth2 deposit contract, which is used under CC0-1.0\n///[link](https://github.com/ethereum/deposit_contract/blob/dev/deposit_contract/contracts/validator_registration.v.py).\n/// With the following changes:\n/// \u003e - Implemented in Solidity 0.7.6 (eth2 deposit contract implemented in Vyper).\n/// \u003e - `H() = keccak256()` is used as the hashing function instead of `sha256()`.\nlibrary MerkleTree {\n    /// @dev For root calculation we need at least one empty leaf, thus the minus one in the formula.\n    uint256 internal constant MAX_LEAVES = 2 ** ORIGIN_TREE_HEIGHT - 1;\n\n    // ═════════════════════════════════════════════════ BASE TREE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Inserts `node` into merkle tree\n     * @dev Reverts if tree is full\n     * @param newCount  Amount of inserted leaves in the tree after the insertion (i.e. current + 1)\n     * @param node      Element to insert into tree\n     */\n    function insertBase(BaseTree storage tree, uint256 newCount, bytes32 node) internal {\n        if (newCount \u003e MAX_LEAVES) revert MerkleTreeFull();\n        // We go up the tree following the branch from the empty leaf AFTER the just inserted one.\n        // We stop when we find the first \"right child\" node.\n        // Its sibling is now the rightmost \"left child\" node that has two non-empty children.\n        // Therefore we need to update `tree.branch` value on this level.\n        // One could see that `tree.branch` value on lower and higher levels remain unchanged.\n\n        // Loop invariant: `node` is the current level's value for the branch from JUST INSERTED leaf\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            if ((newCount \u0026 1) == 1) {\n                // Found the first \"right child\" node on the branch from EMPTY leaf\n                // `node` is the value for node on branch from JUST INSERTED leaf\n                // Which in this case is the \"left child\".\n                // We update tree.branch and exit\n                tree.branch[i] = node;\n                return;\n            }\n            // On the branch from EMPTY leaf this is still a \"left child\".\n            // Meaning on branch from JUST INSERTED leaf, `node` is a right child.\n            // We compute value for `node` parent using `tree.branch` invariant:\n            // This is the rightmost \"left child\" node, which would be sibling of `node`.\n            node = MerkleMath.getParent(tree.branch[i], node);\n            // Get the parent index, and go to the next tree level\n            newCount \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n        // As the loop should always end prematurely with the `return` statement,\n        // this code should be unreachable. We assert `false` just to be safe.\n        assert(false);\n    }\n\n    /**\n     * @notice Calculates and returns current root of the merkle tree.\n     * @param count     Current amount of inserted leaves in the tree\n     * @return current  Calculated root of `tree`\n     */\n    function rootBase(BaseTree storage tree, uint256 count) internal view returns (bytes32 current) {\n        // To calculate the root we follow the branch of first EMPTY leaf (index == count)\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            // Check if we are the left or the right child on the current level\n            if ((count \u0026 1) == 1) {\n                // We are the right child. Our sibling is the \"rightmost\" \"left-child\" node\n                // that has two non-empty children → sibling is `tree.branch[i]`\n                current = MerkleMath.getParent(tree.branch[i], current);\n            } else {\n                // We are the left child. Our sibling does not exist yet → sibling is EMPTY\n                current = MerkleMath.getParent(current, bytes32(0));\n            }\n            // Get the parent index, and go to the next tree level\n            count \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    // ══════════════════════════════════════════════ HISTORICAL TREE ══════════════════════════════════════════════════\n\n    /// @notice Initializes the historical roots for the tree by inserting an empty root.\n    // solhint-disable-next-line ordering\n    function initializeRoots(HistoricalTree storage tree) internal returns (bytes32 savedRoot) {\n        // This should only be called once, when the contract is initialized\n        assert(tree.roots.length == 0);\n        // Save root for empty merkle tree: bytes32(0)\n        tree.roots.push(savedRoot);\n    }\n\n    /// @notice Inserts a new leaf into the merkle tree.\n    /// @dev Reverts if tree is full.\n    /// @param node         Element to insert into tree\n    /// @return newRoot     Merkle root after the leaf was inserted\n    function insert(HistoricalTree storage tree, bytes32 node) internal returns (bytes32 newRoot) {\n        // Tree count after the new leaf will be inserted (we store roots[0] as root of empty tree)\n        uint256 newCount = tree.roots.length;\n        tree.tree.insertBase(newCount, node);\n        // Save the new root\n        newRoot = tree.tree.rootBase(newCount);\n        tree.roots.push(newRoot);\n    }\n\n    /// @notice Returns the historical root of the merkle tree.\n    /// @dev Reverts if not enough leafs have been inserted.\n    /// @param count            Amount of leafs in the tree at some point of time\n    /// @return historicalRoot  Merkle root after `count` leafs were inserted\n    function root(HistoricalTree storage tree, uint256 count) internal view returns (bytes32 historicalRoot) {\n        if (count \u003e= tree.roots.length) revert NotEnoughLeafs();\n        return tree.roots[count];\n    }\n\n    // ═══════════════════════════════════════════════ DYNAMIC TREE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Updates the value for the leaf with the given index in the Dynamic Merkle Tree.\n     * @dev Will revert if incorrect proof of inclusion for old value is supplied.\n     * @param tree          Dynamic merkle tree\n     * @param index         Index of the leaf to update\n     * @param oldValue      Previous value of the leaf\n     * @param branch        Proof of inclusion of previous value into the tree\n     * @param newValue      New leaf value to assign\n     * @return newRoot      New value for the Merkle Root after the leaf is updated\n     */\n    function update(\n        DynamicTree storage tree,\n        uint256 index,\n        bytes32 oldValue,\n        bytes32[] memory branch,\n        bytes32 newValue\n    ) internal returns (bytes32 newRoot) {\n        // Check that the old value + proof result in a correct root\n        if (MerkleMath.proofRoot(index, oldValue, branch, AGENT_TREE_HEIGHT) != tree.root) {\n            revert LeafNotProven();\n        }\n        // New root is new value + the same proof (values for sibling nodes are not updated)\n        newRoot = MerkleMath.proofRoot(index, newValue, branch, AGENT_TREE_HEIGHT);\n        // Write the new root\n        tree.root = newRoot;\n    }\n}\n\n// contracts/libs/stack/Tips.sol\n\n/// Tips is encoded data with \"tips paid for sending a base message\".\n/// Note: even though uint256 is also an underlying type for MemView, Tips is stored ON STACK.\ntype Tips is uint256;\n\nusing TipsLib for Tips global;\n\n/// # Tips\n/// Library for formatting _the tips part_ of _the base messages_.\n///\n/// ## How the tips are awarded\n/// Tips are paid for sending a base message, and are split across all the agents that\n/// made the message execution on destination chain possible.\n/// ### Summit tips\n/// Split between:\n///     - Guard posting a snapshot with state ST_G for the origin chain.\n///     - Notary posting a snapshot SN_N using ST_G. This creates attestation A.\n///     - Notary posting a message receipt after it is executed on destination chain.\n/// ### Attestation tips\n/// Paid to:\n///     - Notary posting attestation A to destination chain.\n/// ### Execution tips\n/// Paid to:\n///     - First executor performing a valid execution attempt (correct proofs, optimistic period over),\n///      using attestation A to prove message inclusion on origin chain, whether the recipient reverted or not.\n/// ### Delivery tips.\n/// Paid to:\n///     - Executor who successfully executed the message on destination chain.\n///\n/// ## Tips encoding\n/// - Tips occupy a single storage word, and thus are stored on stack instead of being stored in memory.\n/// - The actual tip values should be determined by multiplying stored values by divided by TIPS_MULTIPLIER=2**32.\n/// - Tips are packed into a single word of storage, while allowing real values up to ~8*10**28 for every tip category.\n/// \u003e The only downside is that the \"real tip values\" are now multiplies of ~4*10**9, which should be fine even for\n/// the chains with the most expensive gas currency.\n/// # Tips stack layout (from highest bits to lowest)\n///\n/// | Position   | Field          | Type   | Bytes | Description                                                |\n/// | ---------- | -------------- | ------ | ----- | ---------------------------------------------------------- |\n/// | (032..024] | summitTip      | uint64 | 8     | Tip for agents interacting with Summit contract            |\n/// | (024..016] | attestationTip | uint64 | 8     | Tip for Notary posting attestation to Destination contract |\n/// | (016..008] | executionTip   | uint64 | 8     | Tip for valid execution attempt on destination chain       |\n/// | (008..000] | deliveryTip    | uint64 | 8     | Tip for successful message delivery on destination chain   |\n\nlibrary TipsLib {\n    using SafeCast for uint256;\n\n    /// @dev Amount of bits to shift to summitTip field\n    uint256 private constant SHIFT_SUMMIT_TIP = 24 * 8;\n    /// @dev Amount of bits to shift to attestationTip field\n    uint256 private constant SHIFT_ATTESTATION_TIP = 16 * 8;\n    /// @dev Amount of bits to shift to executionTip field\n    uint256 private constant SHIFT_EXECUTION_TIP = 8 * 8;\n\n    // ═══════════════════════════════════════════════════ TIPS ════════════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips with the given fields\n    /// @param summitTip_        Tip for agents interacting with Summit contract, divided by TIPS_MULTIPLIER\n    /// @param attestationTip_   Tip for Notary posting attestation to Destination contract, divided by TIPS_MULTIPLIER\n    /// @param executionTip_     Tip for valid execution attempt on destination chain, divided by TIPS_MULTIPLIER\n    /// @param deliveryTip_      Tip for successful message delivery on destination chain, divided by TIPS_MULTIPLIER\n    function encodeTips(uint64 summitTip_, uint64 attestationTip_, uint64 executionTip_, uint64 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // forgefmt: disable-next-item\n        return Tips.wrap(\n            uint256(summitTip_) \u003c\u003c SHIFT_SUMMIT_TIP |\n            uint256(attestationTip_) \u003c\u003c SHIFT_ATTESTATION_TIP |\n            uint256(executionTip_) \u003c\u003c SHIFT_EXECUTION_TIP |\n            uint256(deliveryTip_)\n        );\n    }\n\n    /// @notice Convenience function to encode tips with uint256 values.\n    function encodeTips256(uint256 summitTip_, uint256 attestationTip_, uint256 executionTip_, uint256 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // In practice, the tips amounts are not supposed to be higher than 2**96, and with 32 bits of granularity\n        // using uint64 is enough to store the values. However, we still check for overflow just in case.\n        // TODO: consider using Number type to store the tips values.\n        return encodeTips({\n            summitTip_: (summitTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            attestationTip_: (attestationTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            executionTip_: (executionTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            deliveryTip_: (deliveryTip_ \u003e\u003e TIPS_GRANULARITY).toUint64()\n        });\n    }\n\n    /// @notice Wraps the padded encoded tips into a Tips-typed value.\n    /// @dev There is no actual padding here, as the underlying type is already uint256,\n    /// but we include this function for consistency and to be future-proof, if tips will eventually use anything\n    /// smaller than uint256.\n    function wrapPadded(uint256 paddedTips) internal pure returns (Tips) {\n        return Tips.wrap(paddedTips);\n    }\n\n    /**\n     * @notice Returns a formatted Tips payload specifying empty tips.\n     * @return Formatted tips\n     */\n    function emptyTips() internal pure returns (Tips) {\n        return Tips.wrap(0);\n    }\n\n    /// @notice Returns tips's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Tips tips) internal pure returns (bytes32 hashedTips) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store tips in scratch space\n            mstore(0, tips)\n            // Compute hash of tips padded to 32 bytes\n            hashedTips := keccak256(0, 32)\n        }\n    }\n\n    // ═══════════════════════════════════════════════ TIPS SLICING ════════════════════════════════════════════════════\n\n    /// @notice Returns summitTip field\n    function summitTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_SUMMIT_TIP);\n    }\n\n    /// @notice Returns attestationTip field\n    function attestationTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_ATTESTATION_TIP);\n    }\n\n    /// @notice Returns executionTip field\n    function executionTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_EXECUTION_TIP);\n    }\n\n    /// @notice Returns deliveryTip field\n    function deliveryTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips));\n    }\n\n    // ════════════════════════════════════════════════ TIPS VALUE ═════════════════════════════════════════════════════\n\n    /// @notice Returns total value of the tips payload.\n    /// This is the sum of the encoded values, scaled up by TIPS_MULTIPLIER\n    function value(Tips tips) internal pure returns (uint256 value_) {\n        value_ = uint256(tips.summitTip()) + tips.attestationTip() + tips.executionTip() + tips.deliveryTip();\n        value_ \u003c\u003c= TIPS_GRANULARITY;\n    }\n\n    /// @notice Increases the delivery tip to match the new value.\n    function matchValue(Tips tips, uint256 newValue) internal pure returns (Tips newTips) {\n        uint256 oldValue = tips.value();\n        if (newValue \u003c oldValue) revert TipsValueTooLow();\n        // We want to increase the delivery tip, while keeping the other tips the same\n        unchecked {\n            uint256 delta = (newValue - oldValue) \u003e\u003e TIPS_GRANULARITY;\n            // `delta` fits into uint224, as TIPS_GRANULARITY is 32, so this never overflows uint256.\n            // In practice, this will never overflow uint64 as well, but we still check it just in case.\n            if (delta + tips.deliveryTip() \u003e type(uint64).max) revert TipsOverflow();\n            // Delivery tips occupy lowest 8 bytes, so we can just add delta to the tips value\n            // to effectively increase the delivery tip (knowing that delta fits into uint64).\n            newTips = Tips.wrap(Tips.unwrap(tips) + delta);\n        }\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    function __Ownable_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable_init_unchained() internal onlyInitializing {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n    function __Ownable2Step_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable2Step_init_unchained() internal onlyInitializing {\n    }\n    address private _pendingOwner;\n\n    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Returns the address of the pending owner.\n     */\n    function pendingOwner() public view virtual returns (address) {\n        return _pendingOwner;\n    }\n\n    /**\n     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual override onlyOwner {\n        _pendingOwner = newOwner;\n        emit OwnershipTransferStarted(owner(), newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual override {\n        delete _pendingOwner;\n        super._transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev The new owner accepts the ownership transfer.\n     */\n    function acceptOwnership() public virtual {\n        address sender = _msgSender();\n        require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n        _transferOwnership(sender);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// contracts/libs/memory/State.sol\n\n/// State is a memory view over a formatted state payload.\ntype State is uint256;\n\nusing StateLib for State global;\n\n/// # State\n/// State structure represents the state of Origin contract at some point of time.\n/// - State is structured in a way to track the updates of the Origin Merkle Tree.\n/// - State includes root of the Origin Merkle Tree, origin domain and some additional metadata.\n/// ## Origin Merkle Tree\n/// Hash of every sent message is inserted in the Origin Merkle Tree, which changes\n/// the value of Origin Merkle Root (which is the root for the mentioned tree).\n/// - Origin has a single Merkle Tree for all messages, regardless of their destination domain.\n/// - This leads to Origin state being updated if and only if a message was sent in a block.\n/// - Origin contract is a \"source of truth\" for states: a state is considered \"valid\" in its Origin,\n/// if it matches the state of the Origin contract after the N-th (nonce) message was sent.\n///\n/// # Memory layout of State fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                    |\n/// | ---------- | ----------- | ------- | ----- | ------------------------------ |\n/// | [000..032) | root        | bytes32 | 32    | Root of the Origin Merkle Tree |\n/// | [032..036) | origin      | uint32  | 4     | Domain where Origin is located |\n/// | [036..040) | nonce       | uint32  | 4     | Amount of sent messages        |\n/// | [040..045) | blockNumber | uint40  | 5     | Block of last sent message     |\n/// | [045..050) | timestamp   | uint40  | 5     | Time of last sent message      |\n/// | [050..062) | gasData     | uint96  | 12    | Gas data for the chain         |\n///\n/// @dev State could be used to form a Snapshot to be signed by a Guard or a Notary.\nlibrary StateLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_ROOT = 0;\n    uint256 private constant OFFSET_ORIGIN = 32;\n    uint256 private constant OFFSET_NONCE = 36;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 40;\n    uint256 private constant OFFSET_TIMESTAMP = 45;\n    uint256 private constant OFFSET_GAS_DATA = 50;\n\n    // ═══════════════════════════════════════════════════ STATE ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted State payload with provided fields\n     * @param root_         New merkle root\n     * @param origin_       Domain of Origin's chain\n     * @param nonce_        Nonce of the merkle root\n     * @param blockNumber_  Block number when root was saved in Origin\n     * @param timestamp_    Block timestamp when root was saved in Origin\n     * @param gasData_      Gas data for the chain\n     * @return Formatted state\n     */\n    function formatState(\n        bytes32 root_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_,\n        GasData gasData_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(root_, origin_, nonce_, blockNumber_, timestamp_, gasData_);\n    }\n\n    /**\n     * @notice Returns a State view over the given payload.\n     * @dev Will revert if the payload is not a state.\n     */\n    function castToState(bytes memory payload) internal pure returns (State) {\n        return castToState(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a State view.\n     * @dev Will revert if the memory view is not over a state.\n     */\n    function castToState(MemView memView) internal pure returns (State) {\n        if (!isState(memView)) revert UnformattedState();\n        return State.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted State.\n    function isState(MemView memView) internal pure returns (bool) {\n        return memView.len() == STATE_LENGTH;\n    }\n\n    /// @notice Returns the hash of a State, that could be later signed by a Guard to signal\n    /// that the state is invalid.\n    function hashInvalid(State state) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(stateInvalidSalt, keccak(state))\n        return state.unwrap().keccakSalted(STATE_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(State state) internal pure returns (MemView) {\n        return MemView.wrap(State.unwrap(state));\n    }\n\n    /// @notice Compares two State structures.\n    function equals(State a, State b) internal pure returns (bool) {\n        // Length of a State payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═══════════════════════════════════════════════ STATE HASHING ═══════════════════════════════════════════════════\n\n    /// @notice Returns the hash of the State.\n    /// @dev We are using the Merkle Root of a tree with two leafs (see below) as state hash.\n    function leaf(State state) internal pure returns (bytes32) {\n        (bytes32 leftLeaf_, bytes32 rightLeaf_) = state.subLeafs();\n        // Final hash is the parent of these leafs\n        return keccak256(bytes.concat(leftLeaf_, rightLeaf_));\n    }\n\n    /// @notice Returns \"sub-leafs\" of the State. Hash of these \"sub leafs\" is going to be used\n    /// as a \"state leaf\" in the \"Snapshot Merkle Tree\".\n    /// This enables proving that leftLeaf = (root, origin) was a part of the \"Snapshot Merkle Tree\",\n    /// by combining `rightLeaf` with the remainder of the \"Snapshot Merkle Proof\".\n    function subLeafs(State state) internal pure returns (bytes32 leftLeaf_, bytes32 rightLeaf_) {\n        MemView memView = state.unwrap();\n        // Left leaf is (root, origin)\n        leftLeaf_ = memView.prefix({len_: OFFSET_NONCE}).keccak();\n        // Right leaf is (metadata), or (nonce, blockNumber, timestamp)\n        rightLeaf_ = memView.sliceFrom({index_: OFFSET_NONCE}).keccak();\n    }\n\n    /// @notice Returns the left \"sub-leaf\" of the State.\n    function leftLeaf(bytes32 root_, uint32 origin_) internal pure returns (bytes32) {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(root_, origin_));\n    }\n\n    /// @notice Returns the right \"sub-leaf\" of the State.\n    function rightLeaf(uint32 nonce_, uint40 blockNumber_, uint40 timestamp_, GasData gasData_)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(nonce_, blockNumber_, timestamp_, gasData_));\n    }\n\n    // ═══════════════════════════════════════════════ STATE SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns a historical Merkle root from the Origin contract.\n    function root(State state) internal pure returns (bytes32) {\n        return state.unwrap().index({index_: OFFSET_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns domain of chain where the Origin contract is deployed.\n    function origin(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns nonce of Origin contract at the time, when `root` was the Merkle root.\n    function nonce(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when `root` was saved in Origin.\n    function blockNumber(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when `root` was saved in Origin.\n    /// @dev This is the timestamp according to the origin chain.\n    function timestamp(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n\n    /// @notice Returns gas data for the chain.\n    function gasData(State state) internal pure returns (GasData) {\n        return GasDataLib.wrapGasData(state.unwrap().indexUint({index_: OFFSET_GAS_DATA, bytes_: GAS_DATA_LENGTH}));\n    }\n}\n\n// contracts/libs/memory/BaseMessage.sol\n\n/// BaseMessage is a memory view over the base message supported by Origin-Destination\ntype BaseMessage is uint256;\n\nusing BaseMessageLib for BaseMessage global;\n\n/// BaseMessage structure represents a base message sent via the Origin-Destination contracts.\n/// - It only contains data relevant to the base message, the rest of data is encoded in the message header.\n/// - `sender` and `recipient` for EVM chains are EVM addresses casted to bytes32, while preserving left-alignment.\n/// - `tips` and `request` parameters are specified by a message sender\n/// \u003e Origin will calculate minimum tips for given request and content length, and will reject messages with tips\n/// lower than that.\n///\n/// # Memory layout of BaseMessage fields\n///\n/// | Position   | Field     | Type    | Bytes | Description                            |\n/// | ---------- | --------- | ------- | ----- | -------------------------------------- |\n/// | [000..032) | tips      | uint256 | 32    | Encoded tips paid on origin chain      |\n/// | [032..064) | sender    | bytes32 | 32    | Sender address on origin chain         |\n/// | [064..096) | recipient | bytes32 | 32    | Recipient address on destination chain |\n/// | [096..116) | request   | uint160 | 20    | Encoded request for message execution  |\n/// | [104..AAA) | content   | bytes   | ??    | Content to be passed to recipient      |\nlibrary BaseMessageLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_TIPS = 0;\n    uint256 private constant OFFSET_SENDER = 32;\n    uint256 private constant OFFSET_RECIPIENT = 64;\n    uint256 private constant OFFSET_REQUEST = OFFSET_RECIPIENT + TIPS_LENGTH;\n    uint256 private constant OFFSET_CONTENT = OFFSET_REQUEST + REQUEST_LENGTH;\n\n    // ═══════════════════════════════════════════════ BASE MESSAGE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted BaseMessage payload with provided fields.\n     * @param tips_         Encoded tips information\n     * @param sender_       Sender address on origin chain\n     * @param recipient_    Recipient address on destination chain\n     * @param request_      Encoded request for message execution\n     * @param content_      Raw content to be passed to recipient on destination chain\n     * @return Formatted base message\n     */\n    function formatBaseMessage(Tips tips_, bytes32 sender_, bytes32 recipient_, Request request_, bytes memory content_)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return abi.encodePacked(tips_, sender_, recipient_, request_, content_);\n    }\n\n    /**\n     * @notice Returns a BaseMessage view over the given payload.\n     * @dev Will revert if the payload is not a base message.\n     */\n    function castToBaseMessage(bytes memory payload) internal pure returns (BaseMessage) {\n        return castToBaseMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a BaseMessage view.\n     * @dev Will revert if the memory view is not over a base message payload.\n     */\n    function castToBaseMessage(MemView memView) internal pure returns (BaseMessage) {\n        if (!isBaseMessage(memView)) revert UnformattedBaseMessage();\n        return BaseMessage.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted BaseMessage.\n    function isBaseMessage(MemView memView) internal pure returns (bool) {\n        // Check if sender, recipient, tips fields exist\n        return (memView.len() \u003e= OFFSET_CONTENT);\n        // Content could be empty, so we don't check that\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(BaseMessage baseMessage) internal pure returns (MemView) {\n        return MemView.wrap(BaseMessage.unwrap(baseMessage));\n    }\n\n    /// @notice Returns baseMessage's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        // We hash \"tips\" and \"everything but tips\" to make tips proofs easier to verify\n        return MerkleMath.getParent(baseMessage.tips().leaf(), baseMessage.bodyLeaf());\n    }\n\n    /// @notice Returns hash for the \"everything but tips\" part of the base message.\n    function bodyLeaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_SENDER}).keccak();\n    }\n\n    // ═══════════════════════════════════════════ BASE MESSAGE SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips paid on origin chain.\n    function tips(BaseMessage baseMessage) internal pure returns (Tips) {\n        return TipsLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_TIPS, bytes_: TIPS_LENGTH})));\n    }\n\n    /// @notice Returns sender address on origin chain.\n    function sender(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_SENDER, bytes_: 32});\n    }\n\n    /// @notice Returns recipient address on destination chain.\n    function recipient(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_RECIPIENT, bytes_: 32});\n    }\n\n    /// @notice Returns an encoded request for message execution on destination chain.\n    function request(BaseMessage baseMessage) internal pure returns (Request) {\n        return RequestLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_REQUEST, bytes_: REQUEST_LENGTH})));\n    }\n\n    /// @notice Returns an untyped memory view over the content to be passed to recipient.\n    function content(BaseMessage baseMessage) internal pure returns (MemView) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_CONTENT});\n    }\n}\n\n// contracts/base/MessagingBase.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for all messaging contracts.\n * - Provides context on the local chain's domain.\n * - Provides ownership functionality.\n * - Will be providing pausing functionality when it is implemented.\n */\nabstract contract MessagingBase is MultiCallable, Versioned, Ownable2StepUpgradeable {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @notice Domain of the local chain, set once upon contract creation\n    uint32 public immutable localDomain;\n    // @notice Domain of the Synapse chain, set once upon contract creation\n    uint32 public immutable synapseDomain;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev gap for upgrade safety\n    uint256[50] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    constructor(string memory version_, uint32 synapseDomain_) Versioned(version_) {\n        localDomain = ChainContext.chainId();\n        synapseDomain = synapseDomain_;\n    }\n\n    // TODO: Implement pausing\n\n    /**\n     * @dev Should be impossible to renounce ownership;\n     * we override OpenZeppelin OwnableUpgradeable's\n     * implementation of renounceOwnership to make it a no-op\n     */\n    function renounceOwnership() public override onlyOwner {} //solhint-disable-line no-empty-blocks\n}\n\n// contracts/libs/memory/Message.sol\n\n/// Message is a memory over over a formatted message payload.\ntype Message is uint256;\n\nusing MessageLib for Message global;\n\n/// Library for formatting the various messages supported by Origin and Destination.\n///\n/// # Message memory layout\n///\n/// | Position   | Field  | Type    | Bytes | Description                                             |\n/// | ---------- | ------ | ------- | ----- | ------------------------------------------------------- |\n/// | [000..017) | header | uint136 | 17    | Encoded general routing information for the message     |\n/// | [017..AAA) | body   | bytes   | ??    | Formatted payload (according to flag) with message body |\nlibrary MessageLib {\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MemViewLib for bytes;\n    using HeaderLib for MemView;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_HEADER = 0;\n    uint256 private constant OFFSET_BODY = OFFSET_HEADER + HEADER_LENGTH;\n\n    // ══════════════════════════════════════════════════ MESSAGE ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns formatted message with provided fields.\n     * @param header_   Encoded general routing information for the message\n     * @param body_     Formatted payload (according to flag) with message body\n     * @return Formatted message\n     */\n    function formatMessage(Header header_, bytes memory body_) internal pure returns (bytes memory) {\n        return abi.encodePacked(header_, body_);\n    }\n\n    /**\n     * @notice Returns a Message view over for the given payload.\n     * @dev Will revert if the payload is not a message payload.\n     */\n    function castToMessage(bytes memory payload) internal pure returns (Message) {\n        return castToMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Message view.\n     * @dev Will revert if the memory view is not over a message payload.\n     */\n    function castToMessage(MemView memView) internal pure returns (Message) {\n        if (!isMessage(memView)) revert UnformattedMessage();\n        return Message.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Message.\n     */\n    function isMessage(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Check if headers exist in the payload\n        if (length \u003c OFFSET_BODY) return false;\n        // Check that Header is valid\n        uint256 paddedHeader = _header(memView);\n        if (!HeaderLib.isHeader(paddedHeader)) return false;\n        // Check that body is formatted according to the flag\n        // Only Base/Manager message flags exist\n        if (HeaderLib.wrapPadded(paddedHeader).flag() == MessageFlag.Base) {\n            // Check if body is a formatted base message\n            return _body(memView).isBaseMessage();\n        } else {\n            // Check if body is a formatted calldata for AgentManager call\n            return _body(memView).isCallData();\n        }\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Message message) internal pure returns (MemView) {\n        return MemView.wrap(Message.unwrap(message));\n    }\n\n    /// @notice Returns message's hash: a leaf to be inserted in the Merkle tree.\n    function leaf(Message message) internal pure returns (bytes32) {\n        // We hash header and body separately to make message proofs easier to verify\n        Header header_ = message.header();\n        // Only Base/Manager message flags exist\n        if (header_.flag() == MessageFlag.Base) {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToBaseMessage().leaf());\n        } else {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToCallData().leaf());\n        }\n    }\n\n    // ══════════════════════════════════════════════ MESSAGE SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns message's encoded header field.\n    function header(Message message) internal pure returns (Header) {\n        return HeaderLib.wrapPadded((message.unwrap().indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH})));\n    }\n\n    /// @notice Returns message's body field as an untyped memory view.\n    function body(Message message) internal pure returns (MemView) {\n        MemView memView = message.unwrap();\n        return _body(memView);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns message's padded header without checking that it is a valid header.\n    function _header(MemView memView) private pure returns (uint256) {\n        return memView.indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH});\n    }\n\n    /// @dev Returns an untyped memory view over the body field without checking\n    /// if the whole payload or the body are properly formatted.\n    function _body(MemView memView) private pure returns (MemView) {\n        return memView.sliceFrom({index_: OFFSET_BODY});\n    }\n}\n\n// contracts/base/AgentSecured.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for messaging contracts that are secured by the agent manager.\n * `AgentSecured` relies on `AgentManager` to provide the following functionality:\n * - Keep track of agents and their statuses.\n * - Pass agent-signed statements that were verified by the agent manager.\n * - These statements are considered valid indefinitely, unless the agent is disputed.\n * - Disputes are opened and resolved by the agent manager.\n * \u003e `AgentSecured` implementation should never use statements signed by agents that are disputed.\n */\nabstract contract AgentSecured is MessagingBase, IAgentSecured {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    address public immutable agentManager;\n\n    /// @inheritdoc IAgentSecured\n    address public immutable inbox;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    // (agent index =\u003e their dispute status: flag, openedAt, resolvedAt)\n    mapping(uint32 =\u003e DisputeStatus) internal _disputes;\n\n    /// @dev gap for upgrade safety\n    uint256[49] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    modifier onlyAgentManager() {\n        if (msg.sender != agentManager) revert CallerNotAgentManager();\n        _;\n    }\n\n    modifier onlyInbox() {\n        if (msg.sender != inbox) revert CallerNotInbox();\n        _;\n    }\n\n    constructor(string memory version_, uint32 synapseDomain_, address agentManager_, address inbox_)\n        MessagingBase(version_, synapseDomain_)\n    {\n        agentManager = agentManager_;\n        inbox = inbox_;\n    }\n\n    // ════════════════════════════════════════════ ONLY AGENT MANAGER ═════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external onlyAgentManager {\n        uint40 openedAt = ChainContext.blockTimestamp();\n        DisputeStatus memory status = DisputeStatus({flag: DisputeFlag.Pending, openedAt: openedAt, resolvedAt: 0});\n        _disputes[guardIndex] = status;\n        _disputes[notaryIndex] = status;\n    }\n\n    /// @inheritdoc IAgentSecured\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external onlyAgentManager {\n        // Update the dispute status of the slashed agent first.\n        uint40 resolvedAt = ChainContext.blockTimestamp();\n        _disputes[slashedIndex].flag = DisputeFlag.Slashed;\n        _disputes[slashedIndex].resolvedAt = resolvedAt;\n        // Mark the rival agent as not disputed, if there was an ongoing dispute.\n        if (rivalIndex != 0) {\n            _disputes[rivalIndex].flag = DisputeFlag.None;\n            _disputes[rivalIndex].resolvedAt = resolvedAt;\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function agentStatus(address agent) external view returns (AgentStatus memory) {\n        return _agentStatus(agent);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status) {\n        return _getAgent(index);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory) {\n        return _disputes[agentIndex];\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns status of the given agent: (flag, domain, index).\n    function _agentStatus(address agent) internal view returns (AgentStatus memory) {\n        return IAgentManager(agentManager).agentStatus(agent);\n    }\n\n    /// @dev Returns agent and their status for a given agent index. Returns zero values for non existing indexes.\n    function _getAgent(uint256 index) internal view returns (address agent, AgentStatus memory status) {\n        return IAgentManager(agentManager).getAgent(index);\n    }\n\n    /// @dev Checks if a Dispute exists for the given Notary. This function returns true, if\n    /// Notary is in ongoing Dispute, or if Dispute was resolved not in Notary's favor.\n    /// In both cases we can't trust Notary's data.\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeExists(uint32 notaryIndex) internal view returns (bool) {\n        return _disputes[notaryIndex].flag != DisputeFlag.None;\n    }\n\n    /// @dev Checks if a Notary recently won a Dispute and is still in the \"post-dispute\" timeout period.\n    /// In this period we still can't trust Notary's data, though we can optimistically assume that\n    /// that the data will be correct after the timeout (assuming no new Disputes are opened).\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeTimeout(uint32 notaryIndex) internal view returns (bool) {\n        DisputeStatus memory status = _disputes[notaryIndex];\n        // Exit early if Notary is in ongoing Dispute / slashed.\n        if (status.flag != DisputeFlag.None) return false;\n        // Check if Notary has been in any Dispute at all.\n        if (status.openedAt == 0) return false;\n        // Otherwise check if the Dispute timeout is still active.\n        return block.timestamp \u003c status.resolvedAt + DISPUTE_TIMEOUT_NOTARY;\n    }\n}\n\n// contracts/hubs/StateHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StateHub` is a parent contract for `Origin`. It is responsible for the following:\n/// - Keeping track of the historical Origin Merkle Tree containing all the message hashes.\n/// - Keeping track of the historical Origin States, as well as verifying their validity.\nabstract contract StateHub is AgentSecured, StateHubEvents, IStateHub {\n    using SafeCast for uint256;\n    using StateLib for bytes;\n\n    struct OriginState {\n        uint40 blockNumber;\n        uint40 timestamp;\n        GasData gasData;\n    }\n    // Bits left for tight packing: 80\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Historical Merkle Tree\n    /// Note: Takes two storage slots\n    HistoricalTree private _tree;\n\n    /// @dev All historical contract States\n    OriginState[] private _originStates;\n\n    /// @dev gap for upgrade safety\n    uint256[47] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IStateHub\n    function isValidState(bytes memory statePayload) external view returns (bool isValid) {\n        // This will revert if payload is not a formatted state\n        State state = statePayload.castToState();\n        return _isValidState(state);\n    }\n\n    /// @inheritdoc IStateHub\n    function statesAmount() external view returns (uint256) {\n        return _originStates.length;\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestLatestState() external view returns (bytes memory stateData) {\n        // This never underflows, assuming the contract was initialized\n        return suggestState(_nextNonce() - 1);\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestState(uint32 nonce) public view returns (bytes memory stateData) {\n        // This will revert if nonce is out of range\n        bytes32 root = _tree.root(nonce);\n        return _formatOriginState(_originStates[nonce], root, localDomain, nonce);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Initializes the saved states list by inserting a state for an empty Merkle Tree.\n    function _initializeStates() internal {\n        // This should only be called once, when the contract is initialized\n        // This will revert if _tree.roots is non-empty\n        bytes32 savedRoot = _tree.initializeRoots();\n        // Save root for empty merkle _tree with block number and timestamp of initialization\n        _saveState(savedRoot, _toOriginState());\n    }\n\n    /// @dev Inserts leaf into the Merkle Tree and saves the updated origin State.\n    function _insertAndSave(bytes32 leaf) internal {\n        bytes32 newRoot = _tree.insert(leaf);\n        _saveState(newRoot, _toOriginState());\n    }\n\n    /// @dev Saves an updated state of the Origin contract\n    function _saveState(bytes32 root, OriginState memory state) internal {\n        uint32 nonce = _nextNonce();\n        _originStates.push(state);\n        // Emit event with raw state data\n        emit StateSaved(_formatOriginState(state, root, localDomain, nonce));\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns nonce of the next sent message: the amount of saved States so far.\n    /// This always equals to \"total amount of sent messages\" plus 1.\n    function _nextNonce() internal view returns (uint32) {\n        // TODO: consider using more than 32 bits for origin nonces\n        return _originStates.length.toUint32();\n    }\n\n    /// @dev Checks if a state is valid, i.e. if it matches the historical one.\n    /// Reverts, if state refers to another Origin contract.\n    function _isValidState(State state) internal view returns (bool) {\n        // Check if state refers to this contract\n        if (state.origin() != localDomain) revert IncorrectOriginDomain();\n        // Check if nonce exists\n        uint32 nonce = state.nonce();\n        if (nonce \u003e= _originStates.length) return false;\n        // Check if state root matches the historical one\n        if (state.root() != _tree.root(nonce)) return false;\n        // Check if state metadata matches the historical one\n        return _areEqual(state, _originStates[nonce]);\n    }\n\n    // ═════════════════════════════════════════════ STRUCT FORMATTING ═════════════════════════════════════════════════\n\n    /// @dev Returns a formatted payload for a stored OriginState.\n    function _formatOriginState(OriginState memory originState, bytes32 root, uint32 origin, uint32 nonce)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return StateLib.formatState({\n            root_: root,\n            origin_: origin,\n            nonce_: nonce,\n            blockNumber_: originState.blockNumber,\n            timestamp_: originState.timestamp,\n            gasData_: originState.gasData\n        });\n    }\n\n    /// @dev Child contract should implement the logic for getting the current gas data from the gas oracle\n    /// to be saved as part of the Origin State.\n    // solhint-disable-next-line ordering\n    function _fetchGasData() internal view virtual returns (GasData);\n\n    /// @dev Returns a OriginState struct to save in the contract.\n    function _toOriginState() internal view returns (OriginState memory originState) {\n        originState.blockNumber = ChainContext.blockNumber();\n        originState.timestamp = ChainContext.blockTimestamp();\n        originState.gasData = _fetchGasData();\n    }\n\n    /// @dev Checks that a state and its Origin representation are equal.\n    function _areEqual(State state, OriginState memory originState) internal pure returns (bool) {\n        return state.blockNumber() == originState.blockNumber \u0026\u0026 state.timestamp() == originState.timestamp;\n    }\n}\n\n// contracts/Origin.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Origin` contract is used for sending messages to remote chains. It is done\n/// by inserting the message hashes into the Origin Merkle, which makes it possible to\n/// prove that message was sent using the Merkle proof against the Origin Merkle Root. This essentially\n/// compresses the list of messages into a single 32-byte value that needs to be stored on the destination chain.\n/// `Origin` is responsible for the following:\n/// - Formatting the sent message payloads, and inserting their hashes into the Origin Merkle Tree.\n/// - Keeping track of its own historical states (see parent contract `StateHub`).\n/// - Enforcing minimum tip values for sent base messages based on the provided execution requests.\n/// - Distributing the collected tips upon request from a local `AgentManager` contract.\ncontract Origin is StateHub, OriginEvents, InterfaceOrigin {\n    using MemViewLib for bytes;\n    using MessageLib for bytes;\n    using TipsLib for bytes;\n    using TypeCasts for address;\n\n    address public immutable gasOracle;\n\n    modifier onlyRemoteDestination(uint32 destination) {\n        if (destination == localDomain) revert IncorrectDestinationDomain();\n        _;\n    }\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_, address gasOracle_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {\n        gasOracle = gasOracle_;\n    }\n\n    /// @notice Initializes Origin contract:\n    /// - msg.sender is set as contract owner\n    /// - State of \"empty merkle tree\" is saved\n    function initialize() external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize \"states\": state of an \"empty merkle tree\" is saved\n        _initializeStates();\n    }\n\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable onlyRemoteDestination(destination) returns (uint32 messageNonce, bytes32 messageHash) {\n        // Check that content is not too large\n        if (content.length \u003e MAX_CONTENT_BYTES) revert ContentLengthTooBig();\n        // This will revert if msg.value is lower than value of minimum tips\n        Tips tips = _getMinimumTips(destination, paddedRequest, content.length).matchValue(msg.value);\n        Request request = RequestLib.wrapPadded(paddedRequest);\n        // Format the BaseMessage body\n        bytes memory body = BaseMessageLib.formatBaseMessage({\n            sender_: msg.sender.addressToBytes32(),\n            recipient_: recipient,\n            tips_: tips,\n            request_: request,\n            content_: content\n        });\n        // Send the message\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Base, body);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        onlyAgentManager\n        onlyRemoteDestination(destination)\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // AgentManager (checked via modifier) is responsible for constructing the calldata payload correctly.\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Manager, payload);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function withdrawTips(address recipient, uint256 amount) external onlyAgentManager {\n        if (address(this).balance \u003c amount) revert InsufficientEthBalance();\n        (bool success,) = recipient.call{value: amount}(\"\");\n        if (!success) revert EthTransferFailed();\n        emit TipWithdrawalCompleted(recipient, amount);\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue)\n    {\n        return _getMinimumTips(destination, paddedRequest, contentLength).value();\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Sends the given message to the specified destination. Message hash is inserted\n    /// into the Origin Merkle Tree, which will enable message execution on destination chain.\n    function _sendMessage(uint32 destination, uint32 optimisticPeriod, MessageFlag flag, bytes memory body)\n        internal\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // Format the message header\n        messageNonce = _nextNonce();\n        Header header = flag.encodeHeader({\n            origin_: localDomain,\n            nonce_: messageNonce,\n            destination_: destination,\n            optimisticPeriod_: optimisticPeriod\n        });\n        // Format the full message payload\n        bytes memory msgPayload = MessageLib.formatMessage(header, body);\n        // Insert new leaf into the Origin Merkle Tree and save the updated state\n        messageHash = msgPayload.castToMessage().leaf();\n        _insertAndSave(messageHash);\n        // Emit event with message information\n        emit Sent(messageHash, messageNonce, destination, msgPayload);\n        // Update the gas oracle data. We do this after the provided tips are checked so that\n        // the provided message is sent in the event that the gas oracle data is updated to a higher value.\n        InterfaceGasOracle(gasOracle).updateGasData(destination);\n        // TODO: consider doing this before the message is sent, while adjusting GasOracle.getMinimumTips() to\n        // use the pending gas oracle data.\n    }\n\n    /// @dev Returns the minimum tips for sending a message to the given destination with the given request and content.\n    function _getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        internal\n        view\n        returns (Tips)\n    {\n        return\n            TipsLib.wrapPadded(InterfaceGasOracle(gasOracle).getMinimumTips(destination, paddedRequest, contentLength));\n    }\n\n    /// @dev Gets the current gas data from the gas oracle to be saved as part of the Origin State.\n    function _fetchGasData() internal view override returns (GasData) {\n        return GasDataLib.wrapGasData(InterfaceGasOracle(gasOracle).getGasData());\n    }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"83268:19162:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;83268:19162:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"83268:19162:0:-:0;;;;;;;;","abiDefinition":[],"userDoc":{"kind":"user","methods":{},"notice":"Library for operations with the memory views. Forked from https://github.com/summa-tx/memview-sol with several breaking changes: - The codebase is ported to Solidity 0.8 - Custom errors are added - The runtime type checking is replaced with compile-time check provided by User-Defined Value Types   https://docs.soliditylang.org/en/latest/types.html#user-defined-value-types - uint256 is used as the underlying type for the \"memory view\" instead of bytes29.   It is wrapped into MemView custom type in order not to be confused with actual integers. - Therefore the \"type\" field is discarded, allowing to allocate 16 bytes for both view location and length - The documentation is expanded - Library functions unused by the rest of the codebase are removed","version":1},"developerDoc":{"kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"Library for operations with the memory views. Forked from https://github.com/summa-tx/memview-sol with several breaking changes: - The codebase is ported to Solidity 0.8 - Custom errors are added - The runtime type checking is replaced with compile-time check provided by User-Defined Value Types   https://docs.soliditylang.org/en/latest/types.html#user-defined-value-types - uint256 is used as the underlying type for the \\\"memory view\\\" instead of bytes29.   It is wrapped into MemView custom type in order not to be confused with actual integers. - Therefore the \\\"type\\\" field is discarded, allowing to allocate 16 bytes for both view location and length - The documentation is expanded - Library functions unused by the rest of the codebase are removed\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Origin.sol\":\"MemViewLib\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Origin.sol\":{\"keccak256\":\"0x96775924f147f3d1f8df8cdf56731fe52a15af8d8e12e608efb8158c112b18cd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e642a27f5fab3c62b4c02e9754e9e42b1cf2e5381dbea9d3d106d23b7772ebe6\",\"dweb:/ipfs/QmUwn7ZyBvPkjnMuK8ZMSexBUdNQnVtxwyoAyT4DXLQjra\"]}},\"version\":1}"},"hashes":{}},"solidity/Origin.sol:MerkleMath":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220403c4121cc61ee0bf1050078f2efbf474d2550a03cc4c7cfb3ef39b430d0ad4b64736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220403c4121cc61ee0bf1050078f2efbf474d2550a03cc4c7cfb3ef39b430d0ad4b64736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/OriginEvents.sol\n\n/// @notice A collection of events emitted by the Origin contract\nabstract contract OriginEvents {\n    /**\n     * @notice Emitted when a new message is sent.\n     * @param messageHash   Hash of message; the leaf inserted to the Merkle tree for the message\n     * @param nonce         Nonce of sent message (starts from 1)\n     * @param destination   Destination domain\n     * @param message       Raw bytes of message\n     */\n    event Sent(bytes32 indexed messageHash, uint32 indexed nonce, uint32 indexed destination, bytes message);\n\n    /**\n     * @notice Emitted when a tip withdrawal is completed.\n     * @param actor     Actor address\n     * @param tip       Tip value, denominated in local domain's wei\n     */\n    event TipWithdrawalCompleted(address actor, uint256 tip);\n}\n\n// contracts/events/StateHubEvents.sol\n\n/// @notice A collection of events emitted by the StateHub contract\nabstract contract StateHubEvents {\n    /**\n     * @notice Emitted when a new Origin State is saved after a message was sent.\n     * @param state     Raw payload with state data\n     */\n    event StateSaved(bytes state);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n    /**\n     * @notice Check that a given state is valid: matches the historical state of Origin contract.\n     * Note: any Agent including an invalid state in their snapshot will be slashed\n     * upon providing the snapshot and agent signature for it to Origin contract.\n     * @dev Will revert if any of these is true:\n     *  - State payload is not properly formatted.\n     * @param statePayload      Raw payload with state data\n     * @return isValid          Whether the provided state is valid\n     */\n    function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns the amount of saved states so far.\n     * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n     */\n    function statesAmount() external view returns (uint256);\n\n    /**\n     * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @return statePayload     Raw payload with the latest state data\n     */\n    function suggestLatestState() external view returns (bytes memory statePayload);\n\n    /**\n     * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @param nonce             Historical nonce to form a state\n     * @return statePayload     Raw payload with historical state data\n     */\n    function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/InterfaceGasOracle.sol\n\ninterface InterfaceGasOracle {\n    /**\n     * @notice Fetches the latest gas data for the chain from `Destination` contract,\n     * and uses it to update the oracle values for the requested chain.\n     * @param domain    Domain to update the gas data for\n     */\n    function updateGasData(uint32 domain) external;\n\n    /**\n     * @notice Returns the gas data for the local chain.\n     */\n    function getGasData() external view returns (uint256 paddedGasData);\n\n    /**\n     * @notice Returns the gas data for the given domain, in the decoded format.\n     * @param domain        Domain of chain to get gas data for\n     * @return gasPrice     Gas price for the chain (in Wei per gas unit)\n     * @return dataPrice    Calldata price (in Wei per byte of content)\n     * @return execBuffer   Tx fee safety buffer for message execution (in Wei)\n     * @return amortAttCost Amortized cost for attestation submission (in Wei)\n     * @return etherPrice   Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n     * @return markup       Markup for the message execution (in BWAD)\n     */\n    function getDecodedGasData(uint32 domain)\n        external\n        view\n        returns (\n            uint256 gasPrice,\n            uint256 dataPrice,\n            uint256 execBuffer,\n            uint256 amortAttCost,\n            uint256 etherPrice,\n            uint256 markup\n        );\n\n    /**\n     * @notice Returns the minimum tips for sending a message to a given destination.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return paddedTips       Padded encoded minimum tips information\n     */\n    function getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 paddedTips);\n}\n\n// contracts/interfaces/InterfaceOrigin.sol\n\ninterface InterfaceOrigin {\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /**\n     * @notice Send a message to the recipient located on destination domain.\n     * @dev Recipient has to conform to IMessageRecipient interface, otherwise message won't be delivered.\n     * Will revert if any of these is true:\n     * - `destination` is equal to contract's local domain\n     * - `content` length is greater than `MAX_CONTENT_BYTES`\n     * - `msg.value` is lower than value of minimum tips for the given message\n     * @param destination           Domain of destination chain\n     * @param recipient             Address of recipient on destination chain as bytes32\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param paddedRequest         Padded encoded message execution request on destination chain\n     * @param content               Raw bytes content of message\n     * @return messageNonce         Nonce of the sent message\n     * @return messageHash          Hash of the sent message\n     */\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable returns (uint32 messageNonce, bytes32 messageHash);\n\n    /**\n     * @notice Send a manager message to the destination domain.\n     * @dev This could only be called by AgentManager, which takes care of encoding the calldata payload.\n     * Note: (msgOrigin, proofMaturity) security args will be added to payload on the destination chain\n     * so that the AgentManager could verify where the Manager Message came from and how mature is the proof.\n     * Note: function is not payable, as no tips are required for sending a manager message.\n     * Will revert if `destination` is equal to contract's local domain.\n     * @param destination           Domain of destination chain\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param payload               Payload for calling AgentManager on destination chain (with extra security args)\n     */\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        returns (uint32 messageNonce, bytes32 messageHash);\n\n    // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Withdraws locked base message tips to the recipient.\n     * @dev Could only be called by a local AgentManager.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function withdrawTips(address recipient, uint256 amount) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the minimum tips value for sending a message to a given destination.\n     * @dev Using at least `tipsValue` as `msg.value` for `sendBaseMessage()`\n     * will guarantee that the message will be accepted.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return tipsValue        Minimum tips value for a message to be accepted\n     */\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue);\n}\n\n// contracts/libs/Constants.sol\n\n// Here we define common constants to enable their easier reusing later.\n\n// ══════════════════════════════════ MERKLE ═══════════════════════════════════\n/// @dev Height of the Agent Merkle Tree\nuint256 constant AGENT_TREE_HEIGHT = 32;\n/// @dev Height of the Origin Merkle Tree\nuint256 constant ORIGIN_TREE_HEIGHT = 32;\n/// @dev Height of the Snapshot Merkle Tree. Allows up to 64 leafs, e.g. up to 32 states\nuint256 constant SNAPSHOT_TREE_HEIGHT = 6;\n// ══════════════════════════════════ STRUCTS ══════════════════════════════════\n/// @dev See Attestation.sol: (bytes32,bytes32,uint32,uint40,uint40): 32+32+4+5+5\nuint256 constant ATTESTATION_LENGTH = 78;\n/// @dev See GasData.sol: (uint16,uint16,uint16,uint16,uint16,uint16): 2+2+2+2+2+2\nuint256 constant GAS_DATA_LENGTH = 12;\n/// @dev See Receipt.sol: (uint32,uint32,bytes32,bytes32,uint8,address,address,address): 4+4+32+32+1+20+20+20\nuint256 constant RECEIPT_LENGTH = 133;\n/// @dev See State.sol: (bytes32,uint32,uint32,uint40,uint40,GasData): 32+4+4+5+5+len(GasData)\nuint256 constant STATE_LENGTH = 50 + GAS_DATA_LENGTH;\n/// @dev Maximum amount of states in a single snapshot. Each state produces two leafs in the tree\nuint256 constant SNAPSHOT_MAX_STATES = 1 \u003c\u003c (SNAPSHOT_TREE_HEIGHT - 1);\n// ══════════════════════════════════ MESSAGE ══════════════════════════════════\n/// @dev See Header.sol: (uint8,uint32,uint32,uint32,uint32): 1+4+4+4+4\nuint256 constant HEADER_LENGTH = 17;\n/// @dev See Request.sol: (uint96,uint64,uint32): 12+8+4\nuint256 constant REQUEST_LENGTH = 24;\n/// @dev See Tips.sol: (uint64,uint64,uint64,uint64): 8+8+8+8\nuint256 constant TIPS_LENGTH = 32;\n/// @dev The amount of discarded last bits when encoding tip values\nuint256 constant TIPS_GRANULARITY = 32;\n/// @dev Tip values could be only the multiples of TIPS_MULTIPLIER\nuint256 constant TIPS_MULTIPLIER = 1 \u003c\u003c TIPS_GRANULARITY;\n// ══════════════════════════════ STATEMENT SALTS ══════════════════════════════\n/// @dev Salts for signing various statements\nbytes32 constant ATTESTATION_VALID_SALT = keccak256(\"ATTESTATION_VALID_SALT\");\nbytes32 constant ATTESTATION_INVALID_SALT = keccak256(\"ATTESTATION_INVALID_SALT\");\nbytes32 constant RECEIPT_VALID_SALT = keccak256(\"RECEIPT_VALID_SALT\");\nbytes32 constant RECEIPT_INVALID_SALT = keccak256(\"RECEIPT_INVALID_SALT\");\nbytes32 constant SNAPSHOT_VALID_SALT = keccak256(\"SNAPSHOT_VALID_SALT\");\nbytes32 constant STATE_INVALID_SALT = keccak256(\"STATE_INVALID_SALT\");\n// ═════════════════════════════════ PROTOCOL ══════════════════════════════════\n/// @dev Optimistic period for new agent roots in LightManager\nuint32 constant AGENT_ROOT_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Timeout between the agent root could be proposed and resolved in LightManager\nuint32 constant AGENT_ROOT_PROPOSAL_TIMEOUT = 12 hours;\nuint32 constant BONDING_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Amount of time that the Notary will not be considered active after they won a dispute\nuint32 constant DISPUTE_TIMEOUT_NOTARY = 12 hours;\n/// @dev Amount of time without fresh data from Notaries before contract owner can resolve stuck disputes manually\nuint256 constant FRESH_DATA_TIMEOUT = 4 hours;\n/// @dev Maximum bytes per message = 2 KiB (somewhat arbitrarily set to begin)\nuint256 constant MAX_CONTENT_BYTES = 2 * 2 ** 10;\n/// @dev Maximum value for the summit tip that could be set in GasOracle\nuint256 constant MAX_SUMMIT_TIP = 0.01 ether;\n\n// contracts/libs/Errors.sol\n\n// ══════════════════════════════ INVALID CALLER ═══════════════════════════════\n\nerror CallerNotAgentManager();\nerror CallerNotDestination();\nerror CallerNotInbox();\nerror CallerNotSummit();\n\n// ══════════════════════════════ INCORRECT DATA ═══════════════════════════════\n\nerror IncorrectAttestation();\nerror IncorrectAgentDomain();\nerror IncorrectAgentIndex();\nerror IncorrectAgentProof();\nerror IncorrectAgentRoot();\nerror IncorrectDataHash();\nerror IncorrectDestinationDomain();\nerror IncorrectOriginDomain();\nerror IncorrectSnapshotProof();\nerror IncorrectSnapshotRoot();\nerror IncorrectState();\nerror IncorrectStatesAmount();\nerror IncorrectTipsProof();\nerror IncorrectVersionLength();\n\nerror IncorrectNonce();\nerror IncorrectSender();\nerror IncorrectRecipient();\n\nerror FlagOutOfRange();\nerror IndexOutOfRange();\nerror NonceOutOfRange();\n\nerror OutdatedNonce();\n\nerror UnformattedAttestation();\nerror UnformattedAttestationReport();\nerror UnformattedBaseMessage();\nerror UnformattedCallData();\nerror UnformattedCallDataPrefix();\nerror UnformattedMessage();\nerror UnformattedReceipt();\nerror UnformattedReceiptReport();\nerror UnformattedSignature();\nerror UnformattedSnapshot();\nerror UnformattedState();\nerror UnformattedStateReport();\n\n// ═══════════════════════════════ MERKLE TREES ════════════════════════════════\n\nerror LeafNotProven();\nerror MerkleTreeFull();\nerror NotEnoughLeafs();\nerror TreeHeightTooLow();\n\n// ═════════════════════════════ OPTIMISTIC PERIOD ═════════════════════════════\n\nerror BaseClientOptimisticPeriod();\nerror MessageOptimisticPeriod();\nerror SlashAgentOptimisticPeriod();\nerror WithdrawTipsOptimisticPeriod();\nerror ZeroProofMaturity();\n\n// ═══════════════════════════════ AGENT MANAGER ═══════════════════════════════\n\nerror AgentNotGuard();\nerror AgentNotNotary();\n\nerror AgentCantBeAdded();\nerror AgentNotActive();\nerror AgentNotActiveNorUnstaking();\nerror AgentNotFraudulent();\nerror AgentNotUnstaking();\nerror AgentUnknown();\n\nerror AgentRootNotProposed();\nerror AgentRootTimeoutNotOver();\n\nerror NotStuck();\n\nerror DisputeAlreadyResolved();\nerror DisputeNotOpened();\nerror DisputeTimeoutNotOver();\nerror GuardInDispute();\nerror NotaryInDispute();\n\nerror MustBeSynapseDomain();\nerror SynapseDomainForbidden();\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\nerror AlreadyExecuted();\nerror AlreadyFailed();\nerror DuplicatedSnapshotRoot();\nerror IncorrectMagicValue();\nerror GasLimitTooLow();\nerror GasSuppliedTooLow();\n\n// ══════════════════════════════════ ORIGIN ═══════════════════════════════════\n\nerror ContentLengthTooBig();\nerror EthTransferFailed();\nerror InsufficientEthBalance();\n\n// ════════════════════════════════ GAS ORACLE ═════════════════════════════════\n\nerror LocalGasDataNotSet();\nerror RemoteGasDataNotSet();\n\n// ═══════════════════════════════════ TIPS ════════════════════════════════════\n\nerror SummitTipTooHigh();\nerror TipsClaimMoreThanEarned();\nerror TipsClaimZero();\nerror TipsOverflow();\nerror TipsValueTooLow();\n\n// ════════════════════════════════ MEMORY VIEW ════════════════════════════════\n\nerror IndexedTooMuch();\nerror ViewOverrun();\nerror OccupiedMemory();\nerror UnallocatedMemory();\nerror PrecompileOutOfGas();\n\n// ═════════════════════════════════ MULTICALL ═════════════════════════════════\n\nerror MulticallFailed();\n\n// contracts/libs/TypeCasts.sol\n\nlibrary TypeCasts {\n    // alignment preserving cast\n    function addressToBytes32(address addr) internal pure returns (bytes32) {\n        return bytes32(uint256(uint160(addr)));\n    }\n\n    // alignment preserving cast\n    function bytes32ToAddress(bytes32 buf) internal pure returns (address) {\n        return address(uint160(uint256(buf)));\n    }\n}\n\n// contracts/libs/stack/Number.sol\n\n/// Number is a compact representation of uint256, that is fit into 16 bits\n/// with the maximum relative error under 0.4%.\ntype Number is uint16;\n\nusing NumberLib for Number global;\n\n/// # Number\n/// Library for compact representation of uint256 numbers.\n/// - Number is stored using mantissa and exponent, each occupying 8 bits.\n/// - Numbers under 2**8 are stored as `mantissa` with `exponent = 0xFF`.\n/// - Numbers at least 2**8 are approximated as `(256 + mantissa) \u003c\u003c exponent`\n/// \u003e - `0 \u003c= mantissa \u003c 256`\n/// \u003e - `0 \u003c= exponent \u003c= 247` (`256 * 2**248` doesn't fit into uint256)\n/// # Number stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type  | Bytes |\n/// | ---------- | -------- | ----- | ----- |\n/// | (002..001] | mantissa | uint8 | 1     |\n/// | (001..000] | exponent | uint8 | 1     |\n\nlibrary NumberLib {\n    /// @dev Amount of bits to shift to mantissa field\n    uint16 private constant SHIFT_MANTISSA = 8;\n\n    /// @notice For bwad math (binary wad) we use 2**64 as \"wad\" unit.\n    /// @dev We are using not using 10**18 as wad, because it is not stored precisely in NumberLib.\n    uint256 internal constant BWAD_SHIFT = 64;\n    uint256 internal constant BWAD = 1 \u003c\u003c BWAD_SHIFT;\n    /// @notice ~0.1% in bwad units.\n    uint256 internal constant PER_MILLE_SHIFT = BWAD_SHIFT - 10;\n    uint256 internal constant PER_MILLE = 1 \u003c\u003c PER_MILLE_SHIFT;\n\n    /// @notice Compresses uint256 number into 16 bits.\n    function compress(uint256 value) internal pure returns (Number) {\n        // Find `msb` such as `2**msb \u003c= value \u003c 2**(msb + 1)`\n        uint256 msb = mostSignificantBit(value);\n        // We want to preserve 9 bits of precision.\n        // The highest bit is always 1, so we can skip it.\n        // The remaining 8 highest bits are stored as mantissa.\n        if (msb \u003c 8) {\n            // Value is less than 2**8, so we can use value as mantissa with \"-1\" exponent.\n            return _encode(uint8(value), 0xFF);\n        } else {\n            // We use `msb - 8` as exponent otherwise. Note that `exponent \u003e= 0`.\n            unchecked {\n                uint256 exponent = msb - 8;\n                // Shifting right by `msb-8` bits will shift the \"remaining 8 highest bits\" into the 8 lowest bits.\n                // uint8() will truncate the highest bit.\n                return _encode(uint8(value \u003e\u003e exponent), uint8(exponent));\n            }\n        }\n    }\n\n    /// @notice Decompresses 16 bits number into uint256.\n    /// @dev The outcome is an approximation of the original number: `(value - value / 256) \u003c number \u003c= value`.\n    function decompress(Number number) internal pure returns (uint256 value) {\n        // Isolate 8 highest bits as the mantissa.\n        uint256 mantissa = Number.unwrap(number) \u003e\u003e SHIFT_MANTISSA;\n        // This will truncate the highest bits, leaving only the exponent.\n        uint256 exponent = uint8(Number.unwrap(number));\n        if (exponent == 0xFF) {\n            return mantissa;\n        } else {\n            unchecked {\n                return (256 + mantissa) \u003c\u003c (exponent);\n            }\n        }\n    }\n\n    /// @dev Returns the most significant bit of `x`\n    /// https://solidity-by-example.org/bitwise/\n    function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\n        // To find `msb` we determine it bit by bit, starting from the highest one.\n        // `0 \u003c= msb \u003c= 255`, so we start from the highest bit, 1\u003c\u003c7 == 128.\n        // If `x` is at least 2**128, then the highest bit of `x` is at least 128.\n        // solhint-disable no-inline-assembly\n        assembly {\n            // `f` is set to 1\u003c\u003c7 if `x \u003e= 2**128` and to 0 otherwise.\n            let f := shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\n            // If `x \u003e= 2**128` then set `msb` highest bit to 1 and shift `x` right by 128.\n            // Otherwise, `msb` remains 0 and `x` remains unchanged.\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        // `x` is now at most 2**128 - 1. Continue the same way, the next highest bit is 1\u003c\u003c6 == 64.\n        assembly {\n            // `f` is set to 1\u003c\u003c6 if `x \u003e= 2**64` and to 0 otherwise.\n            let f := shl(6, gt(x, 0xFFFFFFFFFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c5 if `x \u003e= 2**32` and to 0 otherwise.\n            let f := shl(5, gt(x, 0xFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c4 if `x \u003e= 2**16` and to 0 otherwise.\n            let f := shl(4, gt(x, 0xFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c3 if `x \u003e= 2**8` and to 0 otherwise.\n            let f := shl(3, gt(x, 0xFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c2 if `x \u003e= 2**4` and to 0 otherwise.\n            let f := shl(2, gt(x, 0xF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c1 if `x \u003e= 2**2` and to 0 otherwise.\n            let f := shl(1, gt(x, 0x3))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1 if `x \u003e= 2**1` and to 0 otherwise.\n            let f := gt(x, 0x1)\n            msb := or(msb, f)\n        }\n    }\n\n    /// @dev Wraps (mantissa, exponent) pair into Number.\n    function _encode(uint8 mantissa, uint8 exponent) private pure returns (Number) {\n        // Casts below are upcasts, so they are safe.\n        return Number.wrap(uint16(mantissa) \u003c\u003c SHIFT_MANTISSA | uint16(exponent));\n    }\n}\n\n// contracts/libs/stack/Request.sol\n\n/// Request is encoded data with \"message execution request\".\ntype Request is uint192;\n\nusing RequestLib for Request global;\n\n/// Library for formatting _the request part_ of _the base messages_.\n/// - Request represents a message sender requirements for the message execution on the destination chain.\n/// - Request occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n/// \u003e gasDrop field is included for future compatibility and is ignored at the moment.\n///\n/// # Request stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type   | Bytes | Description                                          |\n/// | ---------- | -------- | ------ | ----- | ---------------------------------------------------- |\n/// | (024..012] | gasDrop  | uint96 | 12    | Minimum amount of gas token to drop to the recipient |\n/// | (012..004] | gasLimit | uint64 | 8     | Minimum amount of gas units to supply for execution  |\n/// | (004..000] | version  | uint32 | 4     | Base message version to pass to the recipient        |\n\nlibrary RequestLib {\n    /// @dev Amount of bits to shift to gasDrop field\n    uint192 private constant SHIFT_GAS_DROP = 12 * 8;\n    /// @dev Amount of bits to shift to gasLimit field\n    uint192 private constant SHIFT_GAS_LIMIT = 4 * 8;\n\n    /// @notice Returns an encoded request with the given fields\n    /// @param gasDrop_     Minimum amount of gas token to drop to the recipient (ignored at the moment)\n    /// @param gasLimit_    Minimum amount of gas units to supply for execution\n    /// @param version_     Base message version to pass to the recipient\n    function encodeRequest(uint96 gasDrop_, uint64 gasLimit_, uint32 version_) internal pure returns (Request) {\n        // Casts below are upcasts, so they are safe\n        return Request.wrap(uint192(gasDrop_) \u003c\u003c SHIFT_GAS_DROP | uint192(gasLimit_) \u003c\u003c SHIFT_GAS_LIMIT | version_);\n    }\n\n    /// @notice Wraps the padded encoded request into a Request-typed value.\n    /// @dev The \"padded\" request is simply an encoded request casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded requests\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedRequest) internal pure returns (Request) {\n        // Casting to uint192 will truncate the highest bits, which is the behavior we want\n        return Request.wrap(uint192(paddedRequest));\n    }\n\n    /// @notice Returns the requested of gas token to drop to the recipient.\n    function gasDrop(Request request) internal pure returns (uint96) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return uint96(Request.unwrap(request) \u003e\u003e SHIFT_GAS_DROP);\n    }\n\n    /// @notice Returns the requested minimum amount of gas units to supply for execution.\n    function gasLimit(Request request) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Request.unwrap(request) \u003e\u003e SHIFT_GAS_LIMIT);\n    }\n\n    /// @notice Returns the requested base message version to pass to the recipient.\n    function version(Request request) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Request.unwrap(request));\n    }\n}\n\n// node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        require(value \u003c= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        require(value \u003c= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        require(value \u003c= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value \u003c= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        require(value \u003c= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        require(value \u003c= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        require(value \u003c= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        require(value \u003c= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        require(value \u003c= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        require(value \u003c= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        require(value \u003c= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        require(value \u003c= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        require(value \u003c= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        require(value \u003c= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        require(value \u003c= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value \u003c= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        require(value \u003c= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        require(value \u003c= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        require(value \u003c= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value \u003c= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        require(value \u003c= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        require(value \u003c= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        require(value \u003c= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value \u003c= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        require(value \u003c= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        require(value \u003c= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        require(value \u003c= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value \u003c= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        require(value \u003c= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value \u003c= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value \u003c= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     *\n     * _Available since v3.0._\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value \u003e= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     *\n     * _Available since v3.0._\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value \u003c= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     *\n     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length \u003e 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance \u003e= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance \u003e= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length \u003e 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n\n// contracts/base/MultiCallable.sol\n\n/// @notice Collection of Multicall utilities. Fork of Multicall3:\n/// https://github.com/mds1/multicall/blob/master/src/Multicall3.sol\nabstract contract MultiCallable {\n    struct Call {\n        bool allowFailure;\n        bytes callData;\n    }\n\n    struct Result {\n        bool success;\n        bytes returnData;\n    }\n\n    /// @notice Aggregates a few calls to this contract into one multicall without modifying `msg.sender`.\n    function multicall(Call[] calldata calls) external returns (Result[] memory callResults) {\n        uint256 amount = calls.length;\n        callResults = new Result[](amount);\n        Call calldata call_;\n        for (uint256 i = 0; i \u003c amount;) {\n            call_ = calls[i];\n            Result memory result = callResults[i];\n            // We perform a delegate call to ourselves here. Delegate call does not modify `msg.sender`, so\n            // this will have the same effect as if `msg.sender` performed all the calls themselves one by one.\n            // solhint-disable-next-line avoid-low-level-calls\n            (result.success, result.returnData) = address(this).delegatecall(call_.callData);\n            // solhint-disable-next-line no-inline-assembly\n            assembly {\n                // Revert if the call fails and failure is not allowed\n                // `allowFailure := calldataload(call_)` and `success := mload(result)`\n                if iszero(or(calldataload(call_), mload(result))) {\n                    // Revert with `0x4d6a2328` (function selector for `MulticallFailed()`)\n                    mstore(0x00, 0x4d6a232800000000000000000000000000000000000000000000000000000000)\n                    revert(0x00, 0x04)\n                }\n            }\n            unchecked {\n                ++i;\n            }\n        }\n    }\n}\n\n// contracts/base/Version.sol\n\n/**\n * @title Versioned\n * @notice Version getter for contracts. Doesn't use any storage slots, meaning\n * it will never cause any troubles with the upgradeable contracts. For instance, this contract\n * can be added or removed from the inheritance chain without shifting the storage layout.\n */\nabstract contract Versioned {\n    /**\n     * @notice Struct that is mimicking the storage layout of a string with 32 bytes or less.\n     * Length is limited by 32, so the whole string payload takes two memory words:\n     * @param length    String length\n     * @param data      String characters\n     */\n    struct _ShortString {\n        uint256 length;\n        bytes32 data;\n    }\n\n    /// @dev Length of the \"version string\"\n    uint256 private immutable _length;\n    /// @dev Bytes representation of the \"version string\".\n    /// Strings with length over 32 are not supported!\n    bytes32 private immutable _data;\n\n    constructor(string memory version_) {\n        _length = bytes(version_).length;\n        if (_length \u003e 32) revert IncorrectVersionLength();\n        // bytes32 is left-aligned =\u003e this will store the byte representation of the string\n        // with the trailing zeroes to complete the 32-byte word\n        _data = bytes32(bytes(version_));\n    }\n\n    function version() external view returns (string memory versionString) {\n        // Load the immutable values to form the version string\n        _ShortString memory str = _ShortString(_length, _data);\n        // The only way to do this cast is doing some dirty assembly\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            versionString := str\n        }\n    }\n}\n\n// contracts/libs/ChainContext.sol\n\n/// @notice Library for accessing chain context variables as tightly packed integers.\n/// Messaging contracts should rely on this library for accessing chain context variables\n/// instead of doing the casting themselves.\nlibrary ChainContext {\n    using SafeCast for uint256;\n\n    /// @notice Returns the current block number as uint40.\n    /// @dev Reverts if block number is greater than 40 bits, which is not supposed to happen\n    /// until the block.timestamp overflows (assuming block time is at least 1 second).\n    function blockNumber() internal view returns (uint40) {\n        return block.number.toUint40();\n    }\n\n    /// @notice Returns the current block timestamp as uint40.\n    /// @dev Reverts if block timestamp is greater than 40 bits, which is\n    /// supposed to happen approximately in year 36835.\n    function blockTimestamp() internal view returns (uint40) {\n        return block.timestamp.toUint40();\n    }\n\n    /// @notice Returns the chain id as uint32.\n    /// @dev Reverts if chain id is greater than 32 bits, which is not\n    /// supposed to happen in production.\n    function chainId() internal view returns (uint32) {\n        return block.chainid.toUint32();\n    }\n}\n\n// contracts/libs/Structures.sol\n\n// Here we define common enums and structures to enable their easier reusing later.\n\n// ═══════════════════════════════ AGENT STATUS ════════════════════════════════\n\n/// @dev Potential statuses for the off-chain bonded agent:\n/// - Unknown: never provided a bond =\u003e signature not valid\n/// - Active: has a bond in BondingManager =\u003e signature valid\n/// - Unstaking: has a bond in BondingManager, initiated the unstaking =\u003e signature not valid\n/// - Resting: used to have a bond in BondingManager, successfully unstaked =\u003e signature not valid\n/// - Fraudulent: proven to commit fraud, value in Merkle Tree not updated =\u003e signature not valid\n/// - Slashed: proven to commit fraud, value in Merkle Tree was updated =\u003e signature not valid\n/// Unstaked agent could later be added back to THE SAME domain by staking a bond again.\n/// Honest agent: Unknown -\u003e Active -\u003e unstaking -\u003e Resting -\u003e Active ...\n/// Malicious agent: Unknown -\u003e Active -\u003e Fraudulent -\u003e Slashed\n/// Malicious agent: Unknown -\u003e Active -\u003e Unstaking -\u003e Fraudulent -\u003e Slashed\nenum AgentFlag {\n    Unknown,\n    Active,\n    Unstaking,\n    Resting,\n    Fraudulent,\n    Slashed\n}\n\n/// @notice Struct for storing an agent in the BondingManager contract.\nstruct AgentStatus {\n    AgentFlag flag;\n    uint32 domain;\n    uint32 index;\n}\n// 184 bits available for tight packing\n\nusing StructureUtils for AgentStatus global;\n\n/// @notice Potential statuses of an agent in terms of being in dispute\n/// - None: agent is not in dispute\n/// - Pending: agent is in unresolved dispute\n/// - Slashed: agent was in dispute that lead to agent being slashed\n/// Note: agent who won the dispute has their status reset to None\nenum DisputeFlag {\n    None,\n    Pending,\n    Slashed\n}\n\n/// @notice Struct for storing dispute status of an agent.\n/// @param flag         Dispute flag: None/Pending/Slashed.\n/// @param openedAt     Timestamp when the latest agent dispute was opened (zero if not opened).\n/// @param resolvedAt   Timestamp when the latest agent dispute was resolved (zero if not resolved).\nstruct DisputeStatus {\n    DisputeFlag flag;\n    uint40 openedAt;\n    uint40 resolvedAt;\n}\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\n/// @notice Struct representing the status of Destination contract.\n/// @param snapRootTime     Timestamp when latest snapshot root was accepted\n/// @param agentRootTime    Timestamp when latest agent root was accepted\n/// @param notaryIndex      Index of Notary who signed the latest agent root\nstruct DestinationStatus {\n    uint40 snapRootTime;\n    uint40 agentRootTime;\n    uint32 notaryIndex;\n}\n\n// ═══════════════════════════════ EXECUTION HUB ═══════════════════════════════\n\n/// @notice Potential statuses of the message in Execution Hub.\n/// - None: there hasn't been a valid attempt to execute the message yet\n/// - Failed: there was a valid attempt to execute the message, but recipient reverted\n/// - Success: there was a valid attempt to execute the message, and recipient did not revert\n/// Note: message can be executed until its status is Success\nenum MessageStatus {\n    None,\n    Failed,\n    Success\n}\n\nlibrary StructureUtils {\n    /// @notice Checks that Agent is Active\n    function verifyActive(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active) {\n            revert AgentNotActive();\n        }\n    }\n\n    /// @notice Checks that Agent is Unstaking\n    function verifyUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Unstaking) {\n            revert AgentNotUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Active or Unstaking\n    function verifyActiveUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active \u0026\u0026 status.flag != AgentFlag.Unstaking) {\n            revert AgentNotActiveNorUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Fraudulent\n    function verifyFraudulent(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Fraudulent) {\n            revert AgentNotFraudulent();\n        }\n    }\n\n    /// @notice Checks that Agent is not Unknown\n    function verifyKnown(AgentStatus memory status) internal pure {\n        if (status.flag == AgentFlag.Unknown) {\n            revert AgentUnknown();\n        }\n    }\n}\n\n// contracts/libs/memory/MemView.sol\n\n/// @dev MemView is an untyped view over a portion of memory to be used instead of `bytes memory`\ntype MemView is uint256;\n\n/// @dev Attach library functions to MemView\nusing MemViewLib for MemView global;\n\n/// @notice Library for operations with the memory views.\n/// Forked from https://github.com/summa-tx/memview-sol with several breaking changes:\n/// - The codebase is ported to Solidity 0.8\n/// - Custom errors are added\n/// - The runtime type checking is replaced with compile-time check provided by User-Defined Value Types\n///   https://docs.soliditylang.org/en/latest/types.html#user-defined-value-types\n/// - uint256 is used as the underlying type for the \"memory view\" instead of bytes29.\n///   It is wrapped into MemView custom type in order not to be confused with actual integers.\n/// - Therefore the \"type\" field is discarded, allowing to allocate 16 bytes for both view location and length\n/// - The documentation is expanded\n/// - Library functions unused by the rest of the codebase are removed\n//  - Very pretty code separators are added :)\nlibrary MemViewLib {\n    /// @notice Stack layout for uint256 (from highest bits to lowest)\n    /// (32 .. 16]      loc     16 bytes    Memory address of underlying bytes\n    /// (16 .. 00]      len     16 bytes    Length of underlying bytes\n\n    // ═══════════════════════════════════════════ BUILDING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Instantiate a new untyped memory view. This should generally not be called directly.\n     * Prefer `ref` wherever possible.\n     * @param loc_          The memory address\n     * @param len_          The length\n     * @return The new view with the specified location and length\n     */\n    function build(uint256 loc_, uint256 len_) internal pure returns (MemView) {\n        uint256 end_ = loc_ + len_;\n        // Make sure that a view is not constructed that points to unallocated memory\n        // as this could be indicative of a buffer overflow attack\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            if gt(end_, mload(0x40)) { end_ := 0 }\n        }\n        if (end_ == 0) {\n            revert UnallocatedMemory();\n        }\n        return _unsafeBuildUnchecked(loc_, len_);\n    }\n\n    /**\n     * @notice Instantiate a memory view from a byte array.\n     * @dev Note that due to Solidity memory representation, it is not possible to\n     * implement a deref, as the `bytes` type stores its len in memory.\n     * @param arr           The byte array\n     * @return The memory view over the provided byte array\n     */\n    function ref(bytes memory arr) internal pure returns (MemView) {\n        uint256 len_ = arr.length;\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 loc_;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // We add 0x20, so that the view starts exactly where the array data starts\n            loc_ := add(arr, 0x20)\n        }\n        return build(loc_, len_);\n    }\n\n    // ════════════════════════════════════════════ CLONING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to the new memory.\n     * @param memView       The memory view\n     * @return arr          The cloned byte array\n     */\n    function clone(MemView memView) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        unchecked {\n            _unsafeCopyTo(memView, ptr + 0x20);\n        }\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 len_ = memView.len();\n        uint256 footprint_ = memView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    /**\n     * @notice Copies all views, joins them into a new bytearray.\n     * @param memViews      The memory views\n     * @return arr          The new byte array with joined data behind the given views\n     */\n    function join(MemView[] memory memViews) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        MemView newView;\n        unchecked {\n            newView = _unsafeJoin(memViews, ptr + 0x20);\n        }\n        uint256 len_ = newView.len();\n        uint256 footprint_ = newView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    // ══════════════════════════════════════════ INSPECTING MEMORY VIEW ═══════════════════════════════════════════════\n\n    /**\n     * @notice Returns the memory address of the underlying bytes.\n     * @param memView       The memory view\n     * @return loc_         The memory address\n     */\n    function loc(MemView memView) internal pure returns (uint256 loc_) {\n        // loc is stored in the highest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u003e\u003e 128;\n    }\n\n    /**\n     * @notice Returns the number of bytes of the view.\n     * @param memView       The memory view\n     * @return len_         The length of the view\n     */\n    function len(MemView memView) internal pure returns (uint256 len_) {\n        // len is stored in the lowest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u0026 type(uint128).max;\n    }\n\n    /**\n     * @notice Returns the endpoint of `memView`.\n     * @param memView       The memory view\n     * @return end_         The endpoint of `memView`\n     */\n    function end(MemView memView) internal pure returns (uint256 end_) {\n        // The endpoint never overflows uint128, let alone uint256, so we could use unchecked math here\n        unchecked {\n            return memView.loc() + memView.len();\n        }\n    }\n\n    /**\n     * @notice Returns the number of memory words this memory view occupies, rounded up.\n     * @param memView       The memory view\n     * @return words_       The number of memory words\n     */\n    function words(MemView memView) internal pure returns (uint256 words_) {\n        // returning ceil(length / 32.0)\n        unchecked {\n            return (memView.len() + 31) \u003e\u003e 5;\n        }\n    }\n\n    /**\n     * @notice Returns the in-memory footprint of a fresh copy of the view.\n     * @param memView       The memory view\n     * @return footprint_   The in-memory footprint of a fresh copy of the view.\n     */\n    function footprint(MemView memView) internal pure returns (uint256 footprint_) {\n        // words() * 32\n        return memView.words() \u003c\u003c 5;\n    }\n\n    // ════════════════════════════════════════════ HASHING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the keccak256 hash of the underlying memory\n     * @param memView       The memory view\n     * @return digest       The keccak256 hash of the underlying memory\n     */\n    function keccak(MemView memView) internal pure returns (bytes32 digest) {\n        uint256 loc_ = memView.loc();\n        uint256 len_ = memView.len();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            digest := keccak256(loc_, len_)\n        }\n    }\n\n    /**\n     * @notice Adds a salt to the keccak256 hash of the underlying data and returns the keccak256 hash of the\n     * resulting data.\n     * @param memView       The memory view\n     * @return digestSalted keccak256(salt, keccak256(memView))\n     */\n    function keccakSalted(MemView memView, bytes32 salt) internal pure returns (bytes32 digestSalted) {\n        return keccak256(bytes.concat(salt, memView.keccak()));\n    }\n\n    // ════════════════════════════════════════════ SLICING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Safe slicing without memory modification.\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the given index\n     */\n    function slice(MemView memView, uint256 index_, uint256 len_) internal pure returns (MemView) {\n        uint256 loc_ = memView.loc();\n        // Ensure it doesn't overrun the view\n        if (loc_ + index_ + len_ \u003e memView.end()) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // loc_ + index_ \u003c= memView.end()\n            return build({loc_: loc_ + index_, len_: len_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing bytes from `index` to end(memView).\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @return The new view for the slice starting from the given index until the initial view endpoint\n     */\n    function sliceFrom(MemView memView, uint256 index_) internal pure returns (MemView) {\n        uint256 len_ = memView.len();\n        // Ensure it doesn't overrun the view\n        if (index_ \u003e len_) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // index_ \u003c= len_ =\u003e memView.loc() + index_ \u003c= memView.loc() + memView.len() == memView.end()\n            return build({loc_: memView.loc() + index_, len_: len_ - index_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the first `len` bytes.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the initial view beginning\n     */\n    function prefix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        return memView.slice({index_: 0, len_: len_});\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the last `len` byte.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length until the initial view endpoint\n     */\n    function postfix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        uint256 viewLen = memView.len();\n        // Ensure it doesn't overrun the view\n        if (len_ \u003e viewLen) {\n            revert ViewOverrun();\n        }\n        // Could do the unchecked math due to the check above\n        uint256 index_;\n        unchecked {\n            index_ = viewLen - len_;\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // len_ \u003c= memView.len() =\u003e memView.loc() \u003c= loc_ \u003c= memView.end()\n            return build({loc_: memView.loc() + viewLen - len_, len_: len_});\n        }\n    }\n\n    // ═══════════════════════════════════════════ INDEXING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Load up to 32 bytes from the view onto the stack.\n     * @dev Returns a bytes32 with only the `bytes_` HIGHEST bytes set.\n     * This can be immediately cast to a smaller fixed-length byte array.\n     * To automatically cast to an integer, use `indexUint`.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return result       The 32 byte result having only `bytes_` highest bytes set\n     */\n    function index(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (bytes32 result) {\n        if (bytes_ == 0) {\n            return bytes32(0);\n        }\n        // Can't load more than 32 bytes to the stack in one go\n        if (bytes_ \u003e 32) {\n            revert IndexedTooMuch();\n        }\n        // The last indexed byte should be within view boundaries\n        if (index_ + bytes_ \u003e memView.len()) {\n            revert ViewOverrun();\n        }\n        uint256 bitLength = bytes_ \u003c\u003c 3; // bytes_ * 8\n        uint256 loc_ = memView.loc();\n        // Get a mask with `bitLength` highest bits set\n        uint256 mask;\n        // 0x800...00 binary representation is 100...00\n        // sar stands for \"signed arithmetic shift\": https://en.wikipedia.org/wiki/Arithmetic_shift\n        // sar(N-1, 100...00) = 11...100..00, with exactly N highest bits set to 1\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            mask := sar(sub(bitLength, 1), 0x8000000000000000000000000000000000000000000000000000000000000000)\n        }\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load a full word using index offset, and apply mask to ignore non-relevant bytes\n            result := and(mload(add(loc_, index_)), mask)\n        }\n    }\n\n    /**\n     * @notice Parse an unsigned integer from the view at `index`.\n     * @dev Requires that the view have \u003e= `bytes_` bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return The unsigned integer\n     */\n    function indexUint(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (uint256) {\n        bytes32 indexedBytes = memView.index(index_, bytes_);\n        // `index()` returns left-aligned `bytes_`, while integers are right-aligned\n        // Shifting here to right-align with the full 32 bytes word: need to shift right `(32 - bytes_)` bytes\n        unchecked {\n            // memView.index() reverts when bytes_ \u003e 32, thus unchecked math\n            return uint256(indexedBytes) \u003e\u003e ((32 - bytes_) \u003c\u003c 3);\n        }\n    }\n\n    /**\n     * @notice Parse an address from the view at `index`.\n     * @dev Requires that the view have \u003e= 20 bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @return The address\n     */\n    function indexAddress(MemView memView, uint256 index_) internal pure returns (address) {\n        // index 20 bytes as `uint160`, and then cast to `address`\n        return address(uint160(memView.indexUint(index_, 20)));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns a memory view over the specified memory location\n    /// without checking if it points to unallocated memory.\n    function _unsafeBuildUnchecked(uint256 loc_, uint256 len_) private pure returns (MemView) {\n        // There is no scenario where loc or len would overflow uint128, so we omit this check.\n        // We use the highest 128 bits to encode the location and the lowest 128 bits to encode the length.\n        return MemView.wrap((loc_ \u003c\u003c 128) | len_);\n    }\n\n    /**\n     * @notice Copy the view to a location, return an unsafe memory reference\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memView       The memory view\n     * @param newLoc        The new location to copy the underlying view data\n     * @return The memory view over the unsafe memory with the copied underlying data\n     */\n    function _unsafeCopyTo(MemView memView, uint256 newLoc) private view returns (MemView) {\n        uint256 len_ = memView.len();\n        uint256 oldLoc = memView.loc();\n\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (newLoc \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        bool res;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // use the identity precompile (0x04) to copy\n            res := staticcall(gas(), 0x04, oldLoc, len_, newLoc, len_)\n        }\n        if (!res) revert PrecompileOutOfGas();\n        return _unsafeBuildUnchecked({loc_: newLoc, len_: len_});\n    }\n\n    /**\n     * @notice Join the views in memory, return an unsafe reference to the memory.\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memViews      The memory views\n     * @return The conjoined view pointing to the new memory\n     */\n    function _unsafeJoin(MemView[] memory memViews, uint256 location) private view returns (MemView) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (location \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        // Copy the views to the specified location one by one, by tracking the amount of copied bytes so far\n        uint256 offset = 0;\n        for (uint256 i = 0; i \u003c memViews.length;) {\n            MemView memView = memViews[i];\n            // We can use the unchecked math here as location + sum(view.length) will never overflow uint256\n            unchecked {\n                _unsafeCopyTo(memView, location + offset);\n                offset += memView.len();\n                ++i;\n            }\n        }\n        return _unsafeBuildUnchecked({loc_: location, len_: offset});\n    }\n}\n\n// contracts/libs/merkle/MerkleMath.sol\n\nlibrary MerkleMath {\n    // ═════════════════════════════════════════ BASIC MERKLE CALCULATIONS ═════════════════════════════════════════════\n\n    /**\n     * @notice Calculates the merkle root for the given leaf and merkle proof.\n     * @dev Will revert if proof length exceeds the tree height.\n     * @param index     Index of `leaf` in tree\n     * @param leaf      Leaf of the merkle tree\n     * @param proof     Proof of inclusion of `leaf` in the tree\n     * @param height    Height of the merkle tree\n     * @return root_    Calculated Merkle Root\n     */\n    function proofRoot(uint256 index, bytes32 leaf, bytes32[] memory proof, uint256 height)\n        internal\n        pure\n        returns (bytes32 root_)\n    {\n        // Proof length could not exceed the tree height\n        uint256 proofLen = proof.length;\n        if (proofLen \u003e height) revert TreeHeightTooLow();\n        root_ = leaf;\n        /// @dev Apply unchecked to all ++h operations\n        unchecked {\n            // Go up the tree levels from the leaf following the proof\n            for (uint256 h = 0; h \u003c proofLen; ++h) {\n                // Get a sibling node on current level: this is proof[h]\n                root_ = getParent(root_, proof[h], index, h);\n            }\n            // Go up to the root: the remaining siblings are EMPTY\n            for (uint256 h = proofLen; h \u003c height; ++h) {\n                root_ = getParent(root_, bytes32(0), index, h);\n            }\n        }\n    }\n\n    /**\n     * @notice Calculates the parent of a node on the path from one of the leafs to root.\n     * @param node          Node on a path from tree leaf to root\n     * @param sibling       Sibling for a given node\n     * @param leafIndex     Index of the tree leaf\n     * @param nodeHeight    \"Level height\" for `node` (ZERO for leafs, ORIGIN_TREE_HEIGHT for root)\n     */\n    function getParent(bytes32 node, bytes32 sibling, uint256 leafIndex, uint256 nodeHeight)\n        internal\n        pure\n        returns (bytes32 parent)\n    {\n        // Index for `node` on its \"tree level\" is (leafIndex / 2**height)\n        // \"Left child\" has even index, \"right child\" has odd index\n        if ((leafIndex \u003e\u003e nodeHeight) \u0026 1 == 0) {\n            // Left child\n            return getParent(node, sibling);\n        } else {\n            // Right child\n            return getParent(sibling, node);\n        }\n    }\n\n    /// @notice Calculates the parent of tow nodes in the merkle tree.\n    /// @dev We use implementation with H(0,0) = 0\n    /// This makes EVERY empty node in the tree equal to ZERO,\n    /// saving us from storing H(0,0), H(H(0,0), H(0, 0)), and so on\n    /// @param leftChild    Left child of the calculated node\n    /// @param rightChild   Right child of the calculated node\n    /// @return parent      Value for the node having above mentioned children\n    function getParent(bytes32 leftChild, bytes32 rightChild) internal pure returns (bytes32 parent) {\n        if (leftChild == bytes32(0) \u0026\u0026 rightChild == bytes32(0)) {\n            return 0;\n        } else {\n            return keccak256(bytes.concat(leftChild, rightChild));\n        }\n    }\n\n    // ════════════════════════════════ ROOT/PROOF CALCULATION FOR A LIST OF LEAFS ═════════════════════════════════════\n\n    /**\n     * @notice Calculates merkle root for a list of given leafs.\n     * Merkle Tree is constructed by padding the list with ZERO values for leafs until list length is `2**height`.\n     * Merkle Root is calculated for the constructed tree, and then saved in `leafs[0]`.\n     * \u003e Note:\n     * \u003e - `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * \u003e - Caller is expected not to reuse `hashes` list after the call, and only use `leafs[0]` value,\n     * which is guaranteed to contain the calculated merkle root.\n     * \u003e - root is calculated using the `H(0,0) = 0` Merkle Tree implementation. See MerkleTree.sol for details.\n     * @dev Amount of leaves should be at most `2**height`\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param height    Height of the Merkle Tree to construct\n     */\n    function calculateRoot(bytes32[] memory hashes, uint256 height) internal pure {\n        uint256 levelLength = hashes.length;\n        // Amount of hashes could not exceed amount of leafs in tree with the given height\n        if (levelLength \u003e (1 \u003c\u003c height)) revert TreeHeightTooLow();\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\": the amount of iterations for the for loop above.\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n            }\n        }\n    }\n\n    /**\n     * @notice Generates a proof of inclusion of a leaf in the list. If the requested index is outside\n     * of the list range, generates a proof of inclusion for an empty leaf (proof of non-inclusion).\n     * The Merkle Tree is constructed by padding the list with ZERO values until list length is a power of two\n     * __AND__ index is in the extended list range. For example:\n     *  - `hashes.length == 6` and `0 \u003c= index \u003c= 7` will \"extend\" the list to 8 entries.\n     *  - `hashes.length == 6` and `7 \u003c index \u003c= 15` will \"extend\" the list to 16 entries.\n     * \u003e Note: `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * Caller is expected not to reuse `hashes` list after the call.\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param index     Leaf index to generate the proof for\n     * @return proof    Generated merkle proof\n     */\n    function calculateProof(bytes32[] memory hashes, uint256 index) internal pure returns (bytes32[] memory proof) {\n        // Use only meaningful values for the shortened proof\n        // Check if index is within the list range (we want to generates proofs for outside leafs as well)\n        uint256 height = getHeight(index \u003c hashes.length ? hashes.length : (index + 1));\n        proof = new bytes32[](height);\n        uint256 levelLength = hashes.length;\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Use sibling for the merkle proof; `index^1` is index of our sibling\n                proof[h] = (index ^ 1 \u003c levelLength) ? hashes[index ^ 1] : bytes32(0);\n\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\"\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n                // Traverse to parent node\n                index \u003e\u003e= 1;\n            }\n        }\n    }\n\n    /// @notice Returns the height of the tree having a given amount of leafs.\n    function getHeight(uint256 leafs) internal pure returns (uint256 height) {\n        uint256 amount = 1;\n        while (amount \u003c leafs) {\n            unchecked {\n                ++height;\n            }\n            amount \u003c\u003c= 1;\n        }\n    }\n}\n\n// contracts/libs/stack/GasData.sol\n\n/// GasData in encoded data with \"basic information about gas prices\" for some chain.\ntype GasData is uint96;\n\nusing GasDataLib for GasData global;\n\n/// ChainGas is encoded data with given chain's \"basic information about gas prices\".\ntype ChainGas is uint128;\n\nusing GasDataLib for ChainGas global;\n\n/// Library for encoding and decoding GasData and ChainGas structs.\n/// # GasData\n/// `GasData` is a struct to store the \"basic information about gas prices\", that could\n/// be later used to approximate the cost of a message execution, and thus derive the\n/// minimal tip values for sending a message to the chain.\n/// \u003e - `GasData` is supposed to be cached by `GasOracle` contract, allowing to store the\n/// \u003e approximates instead of the exact values, and thus save on storage costs.\n/// \u003e - For instance, if `GasOracle` only updates the values on +- 10% change, having an\n/// \u003e 0.4% error on the approximates would be acceptable.\n/// `GasData` is supposed to be included in the Origin's state, which are synced across\n/// chains using Agent-signed snapshots and attestations.\n/// ## GasData stack layout (from highest bits to lowest)\n///\n/// | Position   | Field        | Type   | Bytes | Description                                         |\n/// | ---------- | ------------ | ------ | ----- | --------------------------------------------------- |\n/// | (012..010] | gasPrice     | uint16 | 2     | Gas price for the chain (in Wei per gas unit)       |\n/// | (010..008] | dataPrice    | uint16 | 2     | Calldata price (in Wei per byte of content)         |\n/// | (008..006] | execBuffer   | uint16 | 2     | Tx fee safety buffer for message execution (in Wei) |\n/// | (006..004] | amortAttCost | uint16 | 2     | Amortized cost for attestation submission (in Wei)  |\n/// | (004..002] | etherPrice   | uint16 | 2     | Chain's Ether Price / Mainnet Ether Price (in BWAD) |\n/// | (002..000] | markup       | uint16 | 2     | Markup for the message execution (in BWAD)          |\n/// \u003e See Number.sol for more details on `Number` type and BWAD (binary WAD) math.\n///\n/// ## ChainGas stack layout (from highest bits to lowest)\n///\n/// | Position   | Field   | Type   | Bytes | Description      |\n/// | ---------- | ------- | ------ | ----- | ---------------- |\n/// | (016..004] | gasData | uint96 | 12    | Chain's gas data |\n/// | (004..000] | domain  | uint32 | 4     | Chain's domain   |\nlibrary GasDataLib {\n    /// @dev Amount of bits to shift to gasPrice field\n    uint96 private constant SHIFT_GAS_PRICE = 10 * 8;\n    /// @dev Amount of bits to shift to dataPrice field\n    uint96 private constant SHIFT_DATA_PRICE = 8 * 8;\n    /// @dev Amount of bits to shift to execBuffer field\n    uint96 private constant SHIFT_EXEC_BUFFER = 6 * 8;\n    /// @dev Amount of bits to shift to amortAttCost field\n    uint96 private constant SHIFT_AMORT_ATT_COST = 4 * 8;\n    /// @dev Amount of bits to shift to etherPrice field\n    uint96 private constant SHIFT_ETHER_PRICE = 2 * 8;\n\n    /// @dev Amount of bits to shift to gasData field\n    uint128 private constant SHIFT_GAS_DATA = 4 * 8;\n\n    // ═════════════════════════════════════════════════ GAS DATA ══════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded GasData struct with the given fields.\n    /// @param gasPrice_        Gas price for the chain (in Wei per gas unit)\n    /// @param dataPrice_       Calldata price (in Wei per byte of content)\n    /// @param execBuffer_      Tx fee safety buffer for message execution (in Wei)\n    /// @param amortAttCost_    Amortized cost for attestation submission (in Wei)\n    /// @param etherPrice_      Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n    /// @param markup_          Markup for the message execution (in BWAD)\n    function encodeGasData(\n        Number gasPrice_,\n        Number dataPrice_,\n        Number execBuffer_,\n        Number amortAttCost_,\n        Number etherPrice_,\n        Number markup_\n    ) internal pure returns (GasData) {\n        // Number type wraps uint16, so could safely be casted to uint96\n        // forgefmt: disable-next-item\n        return GasData.wrap(\n            uint96(Number.unwrap(gasPrice_)) \u003c\u003c SHIFT_GAS_PRICE |\n            uint96(Number.unwrap(dataPrice_)) \u003c\u003c SHIFT_DATA_PRICE |\n            uint96(Number.unwrap(execBuffer_)) \u003c\u003c SHIFT_EXEC_BUFFER |\n            uint96(Number.unwrap(amortAttCost_)) \u003c\u003c SHIFT_AMORT_ATT_COST |\n            uint96(Number.unwrap(etherPrice_)) \u003c\u003c SHIFT_ETHER_PRICE |\n            uint96(Number.unwrap(markup_))\n        );\n    }\n\n    /// @notice Wraps padded uint256 value into GasData struct.\n    function wrapGasData(uint256 paddedGasData) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(paddedGasData));\n    }\n\n    /// @notice Returns the gas price, in Wei per gas unit.\n    function gasPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_GAS_PRICE));\n    }\n\n    /// @notice Returns the calldata price, in Wei per byte of content.\n    function dataPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_DATA_PRICE));\n    }\n\n    /// @notice Returns the tx fee safety buffer for message execution, in Wei.\n    function execBuffer(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_EXEC_BUFFER));\n    }\n\n    /// @notice Returns the amortized cost for attestation submission, in Wei.\n    function amortAttCost(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_AMORT_ATT_COST));\n    }\n\n    /// @notice Returns the ratio of Chain's Ether Price / Mainnet Ether Price, in BWAD math.\n    function etherPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_ETHER_PRICE));\n    }\n\n    /// @notice Returns the markup for the message execution, in BWAD math.\n    function markup(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data)));\n    }\n\n    // ════════════════════════════════════════════════ CHAIN DATA ═════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded ChainGas struct with the given fields.\n    /// @param gasData_ Chain's gas data\n    /// @param domain_  Chain's domain\n    function encodeChainGas(GasData gasData_, uint32 domain_) internal pure returns (ChainGas) {\n        // GasData type wraps uint96, so could safely be casted to uint128\n        return ChainGas.wrap(uint128(GasData.unwrap(gasData_)) \u003c\u003c SHIFT_GAS_DATA | uint128(domain_));\n    }\n\n    /// @notice Wraps padded uint256 value into ChainGas struct.\n    function wrapChainGas(uint256 paddedChainGas) internal pure returns (ChainGas) {\n        // Casting to uint128 will truncate the highest bits, which is the behavior we want\n        return ChainGas.wrap(uint128(paddedChainGas));\n    }\n\n    /// @notice Returns the chain's gas data.\n    function gasData(ChainGas data) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(ChainGas.unwrap(data) \u003e\u003e SHIFT_GAS_DATA));\n    }\n\n    /// @notice Returns the chain's domain.\n    function domain(ChainGas data) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(ChainGas.unwrap(data));\n    }\n\n    /// @notice Returns the hash for the list of ChainGas structs.\n    function snapGasHash(ChainGas[] memory snapGas) internal pure returns (bytes32 snapGasHash_) {\n        // Use assembly to calculate the hash of the array without copying it\n        // ChainGas takes a single word of storage, thus ChainGas[] is stored in the following way:\n        // 0x00: length of the array, in words\n        // 0x20: first ChainGas struct\n        // 0x40: second ChainGas struct\n        // And so on...\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Find the location where the array data starts, we add 0x20 to skip the length field\n            let loc := add(snapGas, 0x20)\n            // Load the length of the array (in words).\n            // Shifting left 5 bits is equivalent to multiplying by 32: this converts from words to bytes.\n            let len := shl(5, mload(snapGas))\n            // Calculate the hash of the array\n            snapGasHash_ := keccak256(loc, len)\n        }\n    }\n}\n\n// contracts/libs/stack/Header.sol\n\n/// Header is encoded data with \"general routing information\".\ntype Header is uint136;\n\nusing HeaderLib for Header global;\n\n/// Types of messages supported by Origin-Destination\n/// - Base: message sent by protocol user, contains tips\n/// - Manager: message sent between AgentManager contracts located on different chains, no tips\nenum MessageFlag {\n    Base,\n    Manager\n}\n\nusing HeaderLib for MessageFlag global;\n\n/// Library for formatting _the header part_ of _the messages used by Origin and Destination_.\n/// - Header represents general information for routing a Message for Origin and Destination.\n/// - Header occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n///\n/// # Header stack layout (from highest bits to lowest)\n///\n/// | Position   | Field            | Type   | Bytes | Description                             |\n/// | ---------- | ---------------- | ------ | ----- | --------------------------------------- |\n/// | (017..016] | flag             | uint8  | 1     | Flag specifying the type of message     |\n/// | (016..012] | origin           | uint32 | 4     | Domain where message originated         |\n/// | (012..008] | nonce            | uint32 | 4     | Message nonce on the origin domain      |\n/// | (008..004] | destination      | uint32 | 4     | Domain where message will be executed   |\n/// | (004..000] | optimisticPeriod | uint32 | 4     | Optimistic period that will be enforced |\nlibrary HeaderLib {\n    /// @dev Amount of bits to shift to flag field\n    uint136 private constant SHIFT_FLAG = 16 * 8;\n    /// @dev Amount of bits to shift to origin field\n    uint136 private constant SHIFT_ORIGIN = 12 * 8;\n    /// @dev Amount of bits to shift to nonce field\n    uint136 private constant SHIFT_NONCE = 8 * 8;\n    /// @dev Amount of bits to shift to destination field\n    uint136 private constant SHIFT_DESTINATION = 4 * 8;\n\n    /// @notice Returns an encoded header with provided fields\n    /// @param origin_              Domain of origin chain\n    /// @param nonce_               Message nonce on origin chain\n    /// @param destination_         Domain of destination chain\n    /// @param optimisticPeriod_    Optimistic period for message execution\n    function encodeHeader(\n        MessageFlag flag_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint32 destination_,\n        uint32 optimisticPeriod_\n    ) internal pure returns (Header) {\n        // All casts below are upcasts, so they are safe\n        // forgefmt: disable-next-item\n        return Header.wrap(\n            uint136(uint8(flag_)) \u003c\u003c SHIFT_FLAG |\n            uint136(origin_) \u003c\u003c SHIFT_ORIGIN |\n            uint136(nonce_) \u003c\u003c SHIFT_NONCE |\n            uint136(destination_) \u003c\u003c SHIFT_DESTINATION |\n            uint136(optimisticPeriod_)\n        );\n    }\n\n    /// @notice Checks that the header is a valid encoded header.\n    function isHeader(uint256 paddedHeader) internal pure returns (bool) {\n        // Check that flag is within range\n        return _flag(paddedHeader) \u003c= uint8(type(MessageFlag).max);\n    }\n\n    /// @notice Wraps the padded encoded request into a Header-typed value.\n    /// @dev The \"padded\" header is simply an encoded header casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded headers\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedHeader) internal pure returns (Header) {\n        // Check that flag is within range\n        if (!isHeader(paddedHeader)) revert FlagOutOfRange();\n        // Casting to uint136 will truncate the highest bits, which is the behavior we want\n        return Header.wrap(uint136(paddedHeader));\n    }\n\n    /// @notice Returns header's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Header header) internal pure returns (bytes32 hashedHeader) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store header in scratch space\n            mstore(0, header)\n            // Compute hash of header padded to 32 bytes\n            hashedHeader := keccak256(0, 32)\n        }\n    }\n\n    // ══════════════════════════════════════════════ HEADER SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns header's flag field\n    function flag(Header header) internal pure returns (MessageFlag) {\n        // We check that flag is within range when wrapping the header, so this cast is safe\n        return MessageFlag(_flag(Header.unwrap(header)));\n    }\n\n    /// @notice Returns header's origin field\n    function origin(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_ORIGIN);\n    }\n\n    /// @notice Returns header's nonce field\n    function nonce(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_NONCE);\n    }\n\n    /// @notice Returns header's destination field\n    function destination(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_DESTINATION);\n    }\n\n    /// @notice Returns header's optimistic seconds field\n    function optimisticPeriod(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns header's flag field without casting to MessageFlag\n    function _flag(uint256 paddedHeader) private pure returns (uint8) {\n        // Casting to uint8 will truncate the highest bits, which is the behavior we want\n        return uint8(paddedHeader \u003e\u003e SHIFT_FLAG);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n     * constructor.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall \u0026\u0026 _initialized \u003c 1) || (!AddressUpgradeable.isContract(address(this)) \u0026\u0026 _initialized == 1),\n            \"Initializable: contract is already initialized\"\n        );\n        _initialized = 1;\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: setting the version to 255 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing \u0026\u0026 _initialized \u003c version, \"Initializable: contract is already initialized\");\n        _initialized = version;\n        _initializing = true;\n        _;\n        _initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        require(_initializing, \"Initializable: contract is not initializing\");\n        _;\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized != type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint8) {\n        return _initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _initializing;\n    }\n}\n\n// contracts/interfaces/IAgentManager.sol\n\ninterface IAgentManager {\n    /**\n     * @notice Allows Inbox to open a Dispute between a Guard and a Notary, if they are both not in Dispute already.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Guard or Notary is already in Dispute.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Allows Inbox to slash an agent, if their fraud was proven.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Domain doesn't match the saved agent domain.\n     * @param domain    Domain where the Agent is active\n     * @param agent     Address of the Agent\n     * @param prover    Address that initially provided fraud proof\n     */\n    function slashAgent(uint32 domain, address agent, address prover) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest known root of the Agent Merkle Tree.\n     */\n    function agentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns the number of opened Disputes.\n     * @dev This includes the Disputes that have been resolved already.\n     */\n    function getDisputesAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns information about the dispute with the given index.\n     * @dev Will revert if dispute with given index hasn't been opened yet.\n     * @param index             Dispute index\n     * @return guard            Address of the Guard in the Dispute\n     * @return notary           Address of the Notary in the Dispute\n     * @return slashedAgent     Address of the Agent who was slashed when Dispute was resolved\n     * @return fraudProver      Address who provided fraud proof to resolve the Dispute\n     * @return reportPayload    Raw payload with report data that led to the Dispute\n     * @return reportSignature  Guard signature for the report payload\n     */\n    function getDispute(uint256 index)\n        external\n        view\n        returns (\n            address guard,\n            address notary,\n            address slashedAgent,\n            address fraudProver,\n            bytes memory reportPayload,\n            bytes memory reportSignature\n        );\n\n    /**\n     * @notice Returns the current Dispute status of a given agent. See Structures.sol for details.\n     * @dev Every returned value will be set to zero if agent was not slashed and is not in Dispute.\n     * `rival` and `disputePtr` will be set to zero if the agent was slashed without being in Dispute.\n     * @param agent         Agent address\n     * @return flag         Flag describing the current Dispute status for the agent: None/Pending/Slashed\n     * @return rival        Address of the rival agent in the Dispute\n     * @return fraudProver  Address who provided fraud proof to resolve the Dispute\n     * @return disputePtr   Index of the opened Dispute PLUS ONE. Zero if agent is not in Dispute.\n     */\n    function disputeStatus(address agent)\n        external\n        view\n        returns (DisputeFlag flag, address rival, address fraudProver, uint256 disputePtr);\n}\n\n// contracts/interfaces/IAgentSecured.sol\n\ninterface IAgentSecured {\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * between a Guard and a Notary has been opened.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * has been resolved due to one of the agents being slashed.\n     * \u003e `rivalIndex` will be ZERO, if the slashed agent was not in the Dispute.\n     * @param slashedIndex  Index of the slashed agent in the Agent Merkle Tree\n     * @param rivalIndex    Index of the their Dispute Rival in the Agent Merkle Tree\n     */\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the address of the local AgentManager contract, which is treated as\n     * the \"source of truth\" for agent statuses.\n     */\n    function agentManager() external view returns (address);\n\n    /**\n     * @notice Returns the address of the local Inbox contract, which is treated as\n     * the \"source of truth\" for agent-signed statements.\n     * @dev Inbox passes verified agent statements to `IAgentSecured` contract.\n     */\n    function inbox() external view returns (address);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns (flag, openedAt, resolvedAt) that describes the latest status of\n     * the latest dispute for an agent with a given index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param agentIndex    Agent index in the Agent Merkle Tree\n     * @return              Latest dispute status for the given agent: (flag, openedAt, resolvedAt)\n     */\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory);\n}\n\n// contracts/libs/memory/ByteString.sol\n\n/// @dev CallData is a memory view over the payload to be used for an external call, i.e.\n/// recipient.call(callData). Its length is always (4 + 32 * N) bytes:\n/// - First 4 bytes represent the function selector.\n/// - 32 * N bytes represent N words that function arguments occupy.\ntype CallData is uint256;\n\n/// @dev Attach library functions to CallData\nusing ByteString for CallData global;\n\n/// @dev Signature is a memory view over a \"65 bytes\" array representing a ECDSA signature.\ntype Signature is uint256;\n\n/// @dev Attach library functions to Signature\nusing ByteString for Signature global;\n\nlibrary ByteString {\n    using MemViewLib for bytes;\n\n    /**\n     * @dev non-compact ECDSA signatures are enforced as of OZ 4.7.3\n     *\n     *      Signature payload memory layout\n     * [000 .. 032) r   bytes32 32 bytes\n     * [032 .. 064) s   bytes32 32 bytes\n     * [064 .. 065) v   uint8    1 byte\n     */\n    uint256 internal constant SIGNATURE_LENGTH = 65;\n    uint256 private constant OFFSET_R = 0;\n    uint256 private constant OFFSET_S = 32;\n    uint256 private constant OFFSET_V = 64;\n\n    /**\n     * @dev Calldata memory layout\n     * [000 .. 004) selector    bytes4  4 bytes\n     *      Optional: N function arguments\n     * [004 .. 036) arg1        bytes32 32 bytes\n     *      ..\n     * [AAA .. END) argN        bytes32 32 bytes\n     */\n    uint256 internal constant SELECTOR_LENGTH = 4;\n    uint256 private constant OFFSET_SELECTOR = 0;\n    uint256 private constant OFFSET_ARGUMENTS = SELECTOR_LENGTH;\n\n    // ═════════════════════════════════════════════════ SIGNATURE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the signature payload from the given values.\n     * @dev Using ByteString.formatSignature({r: r, s: s, v: v}) will make sure\n     * that params are given in the right order.\n     */\n    function formatSignature(bytes32 r, bytes32 s, uint8 v) internal pure returns (bytes memory) {\n        return abi.encodePacked(r, s, v);\n    }\n\n    /**\n     * @notice Returns a Signature view over for the given payload.\n     * @dev Will revert if the payload is not a signature.\n     */\n    function castToSignature(bytes memory payload) internal pure returns (Signature) {\n        return castToSignature(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Signature view.\n     * @dev Will revert if the memory view is not over a signature.\n     */\n    function castToSignature(MemView memView) internal pure returns (Signature) {\n        if (!isSignature(memView)) revert UnformattedSignature();\n        return Signature.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a signature\n     */\n    function isSignature(MemView memView) internal pure returns (bool) {\n        return memView.len() == SIGNATURE_LENGTH;\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Signature signature) internal pure returns (MemView) {\n        return MemView.wrap(Signature.unwrap(signature));\n    }\n\n    // ═════════════════════════════════════════════ SIGNATURE SLICING ═════════════════════════════════════════════════\n\n    /// @notice Unpacks signature payload into (r, s, v) parameters.\n    /// @dev Make sure to verify signature length with isSignature() beforehand.\n    function toRSV(Signature signature) internal pure returns (bytes32 r, bytes32 s, uint8 v) {\n        // Get the underlying memory view\n        MemView memView = unwrap(signature);\n        r = memView.index({index_: OFFSET_R, bytes_: 32});\n        s = memView.index({index_: OFFSET_S, bytes_: 32});\n        // Can be safely casted to uint8, since we index a single byte\n        v = uint8(memView.indexUint({index_: OFFSET_V, bytes_: 1}));\n    }\n\n    // ═════════════════════════════════════════════════ CALLDATA ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the calldata with the modified arguments:\n     * the existing arguments are prepended with the arguments from the prefix.\n     * @dev Given:\n     *  - `calldata = abi.encodeWithSelector(foo.selector, d, e);`\n     *  - `prefix = abi.encode(a, b, c);`\n     *  - `a`, `b`, `c` are arguments of static type (i.e. not dynamically sized ones)\n     *      Then:\n     *  - Function will return abi.encodeWithSelector(foo.selector, a, c, c, d, e)\n     *  - Returned calldata will trigger `foo(a, b, c, d, e)` when used for a contract call.\n     * Note: for clarification as to what types are considered static, see\n     * https://docs.soliditylang.org/en/latest/abi-spec.html#formal-specification-of-the-encoding\n     * @param callData  Calldata that needs to be modified\n     * @param prefix    ABI-encoded arguments to use as the first arguments in the new calldata\n     * @return Modified calldata having prefix as the first arguments.\n     */\n    function addPrefix(CallData callData, bytes memory prefix) internal view returns (bytes memory) {\n        // Prefix should occupy a whole amount of words in memory\n        if (!_fullWords(prefix.length)) revert UnformattedCallDataPrefix();\n        MemView[] memory views = new MemView[](3);\n        // Use payload's function selector\n        views[0] = abi.encodePacked(callData.callSelector()).ref();\n        // Use prefix as the first arguments\n        views[1] = prefix.ref();\n        // Use payload's remaining arguments\n        views[2] = callData.arguments();\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a CallData view over for the given payload.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(bytes memory payload) internal pure returns (CallData) {\n        return castToCallData(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a CallData view.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(MemView memView) internal pure returns (CallData) {\n        if (!isCallData(memView)) revert UnformattedCallData();\n        return CallData.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a valid calldata, i.e.\n     * a function selector, followed by arbitrary amount of arguments.\n     */\n    function isCallData(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Calldata should at least have a function selector\n        if (length \u003c SELECTOR_LENGTH) return false;\n        // The remainder of the calldata should be exactly N memory words (N \u003e= 0)\n        return _fullWords(length - SELECTOR_LENGTH);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(CallData callData) internal pure returns (MemView) {\n        return MemView.wrap(CallData.unwrap(callData));\n    }\n\n    /// @notice Returns callData's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(CallData callData) internal pure returns (bytes32) {\n        return callData.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ CALLDATA SLICING ══════════════════════════════════════════════════\n\n    /**\n     * @notice Returns amount of memory words (32 byte chunks) the function arguments\n     * occupy in the calldata.\n     * @dev This might differ from amount of arguments supplied, if any of the arguments\n     * occupies more than one memory slot. It is true, however, that argument part of the payload\n     * occupies exactly N words, even for dynamic types like `bytes`\n     */\n    function argumentWords(CallData callData) internal pure returns (uint256) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        // Equivalent of (length - SELECTOR_LENGTH) / 32\n        return (memView.len() - SELECTOR_LENGTH) \u003e\u003e 5;\n    }\n\n    /// @notice Returns selector for the provided calldata.\n    function callSelector(CallData callData) internal pure returns (bytes4) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return bytes4(memView.index({index_: OFFSET_SELECTOR, bytes_: SELECTOR_LENGTH}));\n    }\n\n    /// @notice Returns abi encoded arguments for the provided calldata.\n    function arguments(CallData callData) internal pure returns (MemView) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return memView.sliceFrom({index_: OFFSET_ARGUMENTS});\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if length is full amount of memory words (32 bytes).\n    function _fullWords(uint256 length) internal pure returns (bool) {\n        // The equivalent of length % 32 == 0\n        return length \u0026 31 == 0;\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n    function __Context_init() internal onlyInitializing {\n    }\n\n    function __Context_init_unchained() internal onlyInitializing {\n    }\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[50] private __gap;\n}\n\n// contracts/libs/merkle/MerkleTree.sol\n\n/// `BaseTree` is a struct representing incremental merkle tree.\n/// - Contains only the current branch.\n/// - The number of inserted leaves is stored externally, and is later supplied for tree operations.\n/// - Has a fixed height of `ORIGIN_TREE_HEIGHT`.\n/// - Can store up to `2 ** ORIGIN_TREE_HEIGHT - 1` leaves.\n/// \u003e Note: the hash function for the tree `H(x, y)` is defined as:\n/// \u003e - `H(0,0) = 0`\n/// \u003e - `H(x,y) = keccak256(x, y), when (x != 0 || y != 0)`\n/// ## Invariant for leafs\n/// - The leftmost empty leaf has `index == count`, where `count` is the amount of the inserted leafs so far.\n/// - Value for any empty leaf or node is bytes32(0).\n/// ## Invariant for current branch\n/// `branch[i]` is always the value of a node on the i-th level.\n/// Levels are numbered from leafs to root: `0 .. ORIGIN_TREE_HEIGHT`.\n/// `branch[i]` stores the value for the node, such that:\n//  - The node is a \"left child\" (e.g. has an even index).\n/// - The node must have two non-empty children.\n/// - Out of all level's \"left child\" nodes with \"non-empty children\",\n/// the one with the biggest index (the rightmost one) is stored as `branch[i]`.\n/// \u003e __`branch` could be used to form a proof of inclusion for the first empty leaf (`index == count`).__\n/// _Here is how:_\n/// - Let's walk along the path from the \"first empty leaf\" to the root.\n/// - i-th bit of the \"first empty leaf\" index (which is equal to `count`) determines if the path's node\n/// for this i-th level is a \"left child\" or a \"right child\".\n/// - i-th bit in `count` is 0 → we are the left child on this level → sibling is the right child\n/// that does not exist yet → `proof[i] = bytes32(0)`.\n/// - i-th bit in `count` is 1 → we are the right child on this level → sibling is the left child\n/// sibling is the rightmost \"left child\" node on the level → `proof[i] = branch[i]`.\n/// \u003e Therefore `proof[i] = (count \u0026 (1 \u003c\u003c i)) == 0 ? bytes32(0) : branch[i])`\nstruct BaseTree {\n    bytes32[ORIGIN_TREE_HEIGHT] branch;\n}\n\nusing MerkleTree for BaseTree global;\n\n/// `HistoricalTree` is an incremental merkle tree keeping track of its historical merkle roots.\n/// \u003e - `roots[N]` is the root of the tree after `N` leafs were inserted\n/// \u003e - `roots[0] == bytes32(0)`\n/// @param tree     Incremental merkle tree\n/// @param roots    Historical merkle roots of the tree\nstruct HistoricalTree {\n    BaseTree tree;\n    bytes32[] roots;\n}\n\nusing MerkleTree for HistoricalTree global;\n\n/// `DynamicTree` is a struct representing a Merkle Tree with `2**AGENT_TREE_HEIGHT` leaves.\n/// - A single operation is available: update value for leaf with an arbitrary index (which might be a non-empty leaf).\n/// - This is done by requesting the proof of inclusion for the old value, which is used to both\n/// verify the old value, and calculate the new root.\n/// \u003e Based on Original idea from [ER forum post](https://ethresear.ch/t/efficient-on-chain-dynamic-merkle-tree/11054).\nstruct DynamicTree {\n    bytes32 root;\n}\n\nusing MerkleTree for DynamicTree global;\n\n/// MerkleTree is work based on Nomad's Merkle.sol, which is used under MIT OR Apache-2.0\n/// [link](https://github.com/nomad-xyz/monorepo/blob/main/packages/contracts-core/contracts/libs/Merkle.sol).\n/// With the following changes:\n/// - Adapted for Solidity 0.8.x.\n/// - Amount of tree leaves stored externally.\n/// - Added thorough documentation.\n/// - `H(0,0) = 0` optimization from [ER forum post](https://ethresear.ch/t/optimizing-sparse-merkle-trees/3751/6).\n/// \u003e Nomad's Merkle.sol is work based on eth2 deposit contract, which is used under CC0-1.0\n///[link](https://github.com/ethereum/deposit_contract/blob/dev/deposit_contract/contracts/validator_registration.v.py).\n/// With the following changes:\n/// \u003e - Implemented in Solidity 0.7.6 (eth2 deposit contract implemented in Vyper).\n/// \u003e - `H() = keccak256()` is used as the hashing function instead of `sha256()`.\nlibrary MerkleTree {\n    /// @dev For root calculation we need at least one empty leaf, thus the minus one in the formula.\n    uint256 internal constant MAX_LEAVES = 2 ** ORIGIN_TREE_HEIGHT - 1;\n\n    // ═════════════════════════════════════════════════ BASE TREE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Inserts `node` into merkle tree\n     * @dev Reverts if tree is full\n     * @param newCount  Amount of inserted leaves in the tree after the insertion (i.e. current + 1)\n     * @param node      Element to insert into tree\n     */\n    function insertBase(BaseTree storage tree, uint256 newCount, bytes32 node) internal {\n        if (newCount \u003e MAX_LEAVES) revert MerkleTreeFull();\n        // We go up the tree following the branch from the empty leaf AFTER the just inserted one.\n        // We stop when we find the first \"right child\" node.\n        // Its sibling is now the rightmost \"left child\" node that has two non-empty children.\n        // Therefore we need to update `tree.branch` value on this level.\n        // One could see that `tree.branch` value on lower and higher levels remain unchanged.\n\n        // Loop invariant: `node` is the current level's value for the branch from JUST INSERTED leaf\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            if ((newCount \u0026 1) == 1) {\n                // Found the first \"right child\" node on the branch from EMPTY leaf\n                // `node` is the value for node on branch from JUST INSERTED leaf\n                // Which in this case is the \"left child\".\n                // We update tree.branch and exit\n                tree.branch[i] = node;\n                return;\n            }\n            // On the branch from EMPTY leaf this is still a \"left child\".\n            // Meaning on branch from JUST INSERTED leaf, `node` is a right child.\n            // We compute value for `node` parent using `tree.branch` invariant:\n            // This is the rightmost \"left child\" node, which would be sibling of `node`.\n            node = MerkleMath.getParent(tree.branch[i], node);\n            // Get the parent index, and go to the next tree level\n            newCount \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n        // As the loop should always end prematurely with the `return` statement,\n        // this code should be unreachable. We assert `false` just to be safe.\n        assert(false);\n    }\n\n    /**\n     * @notice Calculates and returns current root of the merkle tree.\n     * @param count     Current amount of inserted leaves in the tree\n     * @return current  Calculated root of `tree`\n     */\n    function rootBase(BaseTree storage tree, uint256 count) internal view returns (bytes32 current) {\n        // To calculate the root we follow the branch of first EMPTY leaf (index == count)\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            // Check if we are the left or the right child on the current level\n            if ((count \u0026 1) == 1) {\n                // We are the right child. Our sibling is the \"rightmost\" \"left-child\" node\n                // that has two non-empty children → sibling is `tree.branch[i]`\n                current = MerkleMath.getParent(tree.branch[i], current);\n            } else {\n                // We are the left child. Our sibling does not exist yet → sibling is EMPTY\n                current = MerkleMath.getParent(current, bytes32(0));\n            }\n            // Get the parent index, and go to the next tree level\n            count \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    // ══════════════════════════════════════════════ HISTORICAL TREE ══════════════════════════════════════════════════\n\n    /// @notice Initializes the historical roots for the tree by inserting an empty root.\n    // solhint-disable-next-line ordering\n    function initializeRoots(HistoricalTree storage tree) internal returns (bytes32 savedRoot) {\n        // This should only be called once, when the contract is initialized\n        assert(tree.roots.length == 0);\n        // Save root for empty merkle tree: bytes32(0)\n        tree.roots.push(savedRoot);\n    }\n\n    /// @notice Inserts a new leaf into the merkle tree.\n    /// @dev Reverts if tree is full.\n    /// @param node         Element to insert into tree\n    /// @return newRoot     Merkle root after the leaf was inserted\n    function insert(HistoricalTree storage tree, bytes32 node) internal returns (bytes32 newRoot) {\n        // Tree count after the new leaf will be inserted (we store roots[0] as root of empty tree)\n        uint256 newCount = tree.roots.length;\n        tree.tree.insertBase(newCount, node);\n        // Save the new root\n        newRoot = tree.tree.rootBase(newCount);\n        tree.roots.push(newRoot);\n    }\n\n    /// @notice Returns the historical root of the merkle tree.\n    /// @dev Reverts if not enough leafs have been inserted.\n    /// @param count            Amount of leafs in the tree at some point of time\n    /// @return historicalRoot  Merkle root after `count` leafs were inserted\n    function root(HistoricalTree storage tree, uint256 count) internal view returns (bytes32 historicalRoot) {\n        if (count \u003e= tree.roots.length) revert NotEnoughLeafs();\n        return tree.roots[count];\n    }\n\n    // ═══════════════════════════════════════════════ DYNAMIC TREE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Updates the value for the leaf with the given index in the Dynamic Merkle Tree.\n     * @dev Will revert if incorrect proof of inclusion for old value is supplied.\n     * @param tree          Dynamic merkle tree\n     * @param index         Index of the leaf to update\n     * @param oldValue      Previous value of the leaf\n     * @param branch        Proof of inclusion of previous value into the tree\n     * @param newValue      New leaf value to assign\n     * @return newRoot      New value for the Merkle Root after the leaf is updated\n     */\n    function update(\n        DynamicTree storage tree,\n        uint256 index,\n        bytes32 oldValue,\n        bytes32[] memory branch,\n        bytes32 newValue\n    ) internal returns (bytes32 newRoot) {\n        // Check that the old value + proof result in a correct root\n        if (MerkleMath.proofRoot(index, oldValue, branch, AGENT_TREE_HEIGHT) != tree.root) {\n            revert LeafNotProven();\n        }\n        // New root is new value + the same proof (values for sibling nodes are not updated)\n        newRoot = MerkleMath.proofRoot(index, newValue, branch, AGENT_TREE_HEIGHT);\n        // Write the new root\n        tree.root = newRoot;\n    }\n}\n\n// contracts/libs/stack/Tips.sol\n\n/// Tips is encoded data with \"tips paid for sending a base message\".\n/// Note: even though uint256 is also an underlying type for MemView, Tips is stored ON STACK.\ntype Tips is uint256;\n\nusing TipsLib for Tips global;\n\n/// # Tips\n/// Library for formatting _the tips part_ of _the base messages_.\n///\n/// ## How the tips are awarded\n/// Tips are paid for sending a base message, and are split across all the agents that\n/// made the message execution on destination chain possible.\n/// ### Summit tips\n/// Split between:\n///     - Guard posting a snapshot with state ST_G for the origin chain.\n///     - Notary posting a snapshot SN_N using ST_G. This creates attestation A.\n///     - Notary posting a message receipt after it is executed on destination chain.\n/// ### Attestation tips\n/// Paid to:\n///     - Notary posting attestation A to destination chain.\n/// ### Execution tips\n/// Paid to:\n///     - First executor performing a valid execution attempt (correct proofs, optimistic period over),\n///      using attestation A to prove message inclusion on origin chain, whether the recipient reverted or not.\n/// ### Delivery tips.\n/// Paid to:\n///     - Executor who successfully executed the message on destination chain.\n///\n/// ## Tips encoding\n/// - Tips occupy a single storage word, and thus are stored on stack instead of being stored in memory.\n/// - The actual tip values should be determined by multiplying stored values by divided by TIPS_MULTIPLIER=2**32.\n/// - Tips are packed into a single word of storage, while allowing real values up to ~8*10**28 for every tip category.\n/// \u003e The only downside is that the \"real tip values\" are now multiplies of ~4*10**9, which should be fine even for\n/// the chains with the most expensive gas currency.\n/// # Tips stack layout (from highest bits to lowest)\n///\n/// | Position   | Field          | Type   | Bytes | Description                                                |\n/// | ---------- | -------------- | ------ | ----- | ---------------------------------------------------------- |\n/// | (032..024] | summitTip      | uint64 | 8     | Tip for agents interacting with Summit contract            |\n/// | (024..016] | attestationTip | uint64 | 8     | Tip for Notary posting attestation to Destination contract |\n/// | (016..008] | executionTip   | uint64 | 8     | Tip for valid execution attempt on destination chain       |\n/// | (008..000] | deliveryTip    | uint64 | 8     | Tip for successful message delivery on destination chain   |\n\nlibrary TipsLib {\n    using SafeCast for uint256;\n\n    /// @dev Amount of bits to shift to summitTip field\n    uint256 private constant SHIFT_SUMMIT_TIP = 24 * 8;\n    /// @dev Amount of bits to shift to attestationTip field\n    uint256 private constant SHIFT_ATTESTATION_TIP = 16 * 8;\n    /// @dev Amount of bits to shift to executionTip field\n    uint256 private constant SHIFT_EXECUTION_TIP = 8 * 8;\n\n    // ═══════════════════════════════════════════════════ TIPS ════════════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips with the given fields\n    /// @param summitTip_        Tip for agents interacting with Summit contract, divided by TIPS_MULTIPLIER\n    /// @param attestationTip_   Tip for Notary posting attestation to Destination contract, divided by TIPS_MULTIPLIER\n    /// @param executionTip_     Tip for valid execution attempt on destination chain, divided by TIPS_MULTIPLIER\n    /// @param deliveryTip_      Tip for successful message delivery on destination chain, divided by TIPS_MULTIPLIER\n    function encodeTips(uint64 summitTip_, uint64 attestationTip_, uint64 executionTip_, uint64 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // forgefmt: disable-next-item\n        return Tips.wrap(\n            uint256(summitTip_) \u003c\u003c SHIFT_SUMMIT_TIP |\n            uint256(attestationTip_) \u003c\u003c SHIFT_ATTESTATION_TIP |\n            uint256(executionTip_) \u003c\u003c SHIFT_EXECUTION_TIP |\n            uint256(deliveryTip_)\n        );\n    }\n\n    /// @notice Convenience function to encode tips with uint256 values.\n    function encodeTips256(uint256 summitTip_, uint256 attestationTip_, uint256 executionTip_, uint256 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // In practice, the tips amounts are not supposed to be higher than 2**96, and with 32 bits of granularity\n        // using uint64 is enough to store the values. However, we still check for overflow just in case.\n        // TODO: consider using Number type to store the tips values.\n        return encodeTips({\n            summitTip_: (summitTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            attestationTip_: (attestationTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            executionTip_: (executionTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            deliveryTip_: (deliveryTip_ \u003e\u003e TIPS_GRANULARITY).toUint64()\n        });\n    }\n\n    /// @notice Wraps the padded encoded tips into a Tips-typed value.\n    /// @dev There is no actual padding here, as the underlying type is already uint256,\n    /// but we include this function for consistency and to be future-proof, if tips will eventually use anything\n    /// smaller than uint256.\n    function wrapPadded(uint256 paddedTips) internal pure returns (Tips) {\n        return Tips.wrap(paddedTips);\n    }\n\n    /**\n     * @notice Returns a formatted Tips payload specifying empty tips.\n     * @return Formatted tips\n     */\n    function emptyTips() internal pure returns (Tips) {\n        return Tips.wrap(0);\n    }\n\n    /// @notice Returns tips's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Tips tips) internal pure returns (bytes32 hashedTips) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store tips in scratch space\n            mstore(0, tips)\n            // Compute hash of tips padded to 32 bytes\n            hashedTips := keccak256(0, 32)\n        }\n    }\n\n    // ═══════════════════════════════════════════════ TIPS SLICING ════════════════════════════════════════════════════\n\n    /// @notice Returns summitTip field\n    function summitTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_SUMMIT_TIP);\n    }\n\n    /// @notice Returns attestationTip field\n    function attestationTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_ATTESTATION_TIP);\n    }\n\n    /// @notice Returns executionTip field\n    function executionTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_EXECUTION_TIP);\n    }\n\n    /// @notice Returns deliveryTip field\n    function deliveryTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips));\n    }\n\n    // ════════════════════════════════════════════════ TIPS VALUE ═════════════════════════════════════════════════════\n\n    /// @notice Returns total value of the tips payload.\n    /// This is the sum of the encoded values, scaled up by TIPS_MULTIPLIER\n    function value(Tips tips) internal pure returns (uint256 value_) {\n        value_ = uint256(tips.summitTip()) + tips.attestationTip() + tips.executionTip() + tips.deliveryTip();\n        value_ \u003c\u003c= TIPS_GRANULARITY;\n    }\n\n    /// @notice Increases the delivery tip to match the new value.\n    function matchValue(Tips tips, uint256 newValue) internal pure returns (Tips newTips) {\n        uint256 oldValue = tips.value();\n        if (newValue \u003c oldValue) revert TipsValueTooLow();\n        // We want to increase the delivery tip, while keeping the other tips the same\n        unchecked {\n            uint256 delta = (newValue - oldValue) \u003e\u003e TIPS_GRANULARITY;\n            // `delta` fits into uint224, as TIPS_GRANULARITY is 32, so this never overflows uint256.\n            // In practice, this will never overflow uint64 as well, but we still check it just in case.\n            if (delta + tips.deliveryTip() \u003e type(uint64).max) revert TipsOverflow();\n            // Delivery tips occupy lowest 8 bytes, so we can just add delta to the tips value\n            // to effectively increase the delivery tip (knowing that delta fits into uint64).\n            newTips = Tips.wrap(Tips.unwrap(tips) + delta);\n        }\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    function __Ownable_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable_init_unchained() internal onlyInitializing {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n    function __Ownable2Step_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable2Step_init_unchained() internal onlyInitializing {\n    }\n    address private _pendingOwner;\n\n    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Returns the address of the pending owner.\n     */\n    function pendingOwner() public view virtual returns (address) {\n        return _pendingOwner;\n    }\n\n    /**\n     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual override onlyOwner {\n        _pendingOwner = newOwner;\n        emit OwnershipTransferStarted(owner(), newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual override {\n        delete _pendingOwner;\n        super._transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev The new owner accepts the ownership transfer.\n     */\n    function acceptOwnership() public virtual {\n        address sender = _msgSender();\n        require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n        _transferOwnership(sender);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// contracts/libs/memory/State.sol\n\n/// State is a memory view over a formatted state payload.\ntype State is uint256;\n\nusing StateLib for State global;\n\n/// # State\n/// State structure represents the state of Origin contract at some point of time.\n/// - State is structured in a way to track the updates of the Origin Merkle Tree.\n/// - State includes root of the Origin Merkle Tree, origin domain and some additional metadata.\n/// ## Origin Merkle Tree\n/// Hash of every sent message is inserted in the Origin Merkle Tree, which changes\n/// the value of Origin Merkle Root (which is the root for the mentioned tree).\n/// - Origin has a single Merkle Tree for all messages, regardless of their destination domain.\n/// - This leads to Origin state being updated if and only if a message was sent in a block.\n/// - Origin contract is a \"source of truth\" for states: a state is considered \"valid\" in its Origin,\n/// if it matches the state of the Origin contract after the N-th (nonce) message was sent.\n///\n/// # Memory layout of State fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                    |\n/// | ---------- | ----------- | ------- | ----- | ------------------------------ |\n/// | [000..032) | root        | bytes32 | 32    | Root of the Origin Merkle Tree |\n/// | [032..036) | origin      | uint32  | 4     | Domain where Origin is located |\n/// | [036..040) | nonce       | uint32  | 4     | Amount of sent messages        |\n/// | [040..045) | blockNumber | uint40  | 5     | Block of last sent message     |\n/// | [045..050) | timestamp   | uint40  | 5     | Time of last sent message      |\n/// | [050..062) | gasData     | uint96  | 12    | Gas data for the chain         |\n///\n/// @dev State could be used to form a Snapshot to be signed by a Guard or a Notary.\nlibrary StateLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_ROOT = 0;\n    uint256 private constant OFFSET_ORIGIN = 32;\n    uint256 private constant OFFSET_NONCE = 36;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 40;\n    uint256 private constant OFFSET_TIMESTAMP = 45;\n    uint256 private constant OFFSET_GAS_DATA = 50;\n\n    // ═══════════════════════════════════════════════════ STATE ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted State payload with provided fields\n     * @param root_         New merkle root\n     * @param origin_       Domain of Origin's chain\n     * @param nonce_        Nonce of the merkle root\n     * @param blockNumber_  Block number when root was saved in Origin\n     * @param timestamp_    Block timestamp when root was saved in Origin\n     * @param gasData_      Gas data for the chain\n     * @return Formatted state\n     */\n    function formatState(\n        bytes32 root_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_,\n        GasData gasData_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(root_, origin_, nonce_, blockNumber_, timestamp_, gasData_);\n    }\n\n    /**\n     * @notice Returns a State view over the given payload.\n     * @dev Will revert if the payload is not a state.\n     */\n    function castToState(bytes memory payload) internal pure returns (State) {\n        return castToState(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a State view.\n     * @dev Will revert if the memory view is not over a state.\n     */\n    function castToState(MemView memView) internal pure returns (State) {\n        if (!isState(memView)) revert UnformattedState();\n        return State.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted State.\n    function isState(MemView memView) internal pure returns (bool) {\n        return memView.len() == STATE_LENGTH;\n    }\n\n    /// @notice Returns the hash of a State, that could be later signed by a Guard to signal\n    /// that the state is invalid.\n    function hashInvalid(State state) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(stateInvalidSalt, keccak(state))\n        return state.unwrap().keccakSalted(STATE_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(State state) internal pure returns (MemView) {\n        return MemView.wrap(State.unwrap(state));\n    }\n\n    /// @notice Compares two State structures.\n    function equals(State a, State b) internal pure returns (bool) {\n        // Length of a State payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═══════════════════════════════════════════════ STATE HASHING ═══════════════════════════════════════════════════\n\n    /// @notice Returns the hash of the State.\n    /// @dev We are using the Merkle Root of a tree with two leafs (see below) as state hash.\n    function leaf(State state) internal pure returns (bytes32) {\n        (bytes32 leftLeaf_, bytes32 rightLeaf_) = state.subLeafs();\n        // Final hash is the parent of these leafs\n        return keccak256(bytes.concat(leftLeaf_, rightLeaf_));\n    }\n\n    /// @notice Returns \"sub-leafs\" of the State. Hash of these \"sub leafs\" is going to be used\n    /// as a \"state leaf\" in the \"Snapshot Merkle Tree\".\n    /// This enables proving that leftLeaf = (root, origin) was a part of the \"Snapshot Merkle Tree\",\n    /// by combining `rightLeaf` with the remainder of the \"Snapshot Merkle Proof\".\n    function subLeafs(State state) internal pure returns (bytes32 leftLeaf_, bytes32 rightLeaf_) {\n        MemView memView = state.unwrap();\n        // Left leaf is (root, origin)\n        leftLeaf_ = memView.prefix({len_: OFFSET_NONCE}).keccak();\n        // Right leaf is (metadata), or (nonce, blockNumber, timestamp)\n        rightLeaf_ = memView.sliceFrom({index_: OFFSET_NONCE}).keccak();\n    }\n\n    /// @notice Returns the left \"sub-leaf\" of the State.\n    function leftLeaf(bytes32 root_, uint32 origin_) internal pure returns (bytes32) {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(root_, origin_));\n    }\n\n    /// @notice Returns the right \"sub-leaf\" of the State.\n    function rightLeaf(uint32 nonce_, uint40 blockNumber_, uint40 timestamp_, GasData gasData_)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(nonce_, blockNumber_, timestamp_, gasData_));\n    }\n\n    // ═══════════════════════════════════════════════ STATE SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns a historical Merkle root from the Origin contract.\n    function root(State state) internal pure returns (bytes32) {\n        return state.unwrap().index({index_: OFFSET_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns domain of chain where the Origin contract is deployed.\n    function origin(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns nonce of Origin contract at the time, when `root` was the Merkle root.\n    function nonce(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when `root` was saved in Origin.\n    function blockNumber(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when `root` was saved in Origin.\n    /// @dev This is the timestamp according to the origin chain.\n    function timestamp(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n\n    /// @notice Returns gas data for the chain.\n    function gasData(State state) internal pure returns (GasData) {\n        return GasDataLib.wrapGasData(state.unwrap().indexUint({index_: OFFSET_GAS_DATA, bytes_: GAS_DATA_LENGTH}));\n    }\n}\n\n// contracts/libs/memory/BaseMessage.sol\n\n/// BaseMessage is a memory view over the base message supported by Origin-Destination\ntype BaseMessage is uint256;\n\nusing BaseMessageLib for BaseMessage global;\n\n/// BaseMessage structure represents a base message sent via the Origin-Destination contracts.\n/// - It only contains data relevant to the base message, the rest of data is encoded in the message header.\n/// - `sender` and `recipient` for EVM chains are EVM addresses casted to bytes32, while preserving left-alignment.\n/// - `tips` and `request` parameters are specified by a message sender\n/// \u003e Origin will calculate minimum tips for given request and content length, and will reject messages with tips\n/// lower than that.\n///\n/// # Memory layout of BaseMessage fields\n///\n/// | Position   | Field     | Type    | Bytes | Description                            |\n/// | ---------- | --------- | ------- | ----- | -------------------------------------- |\n/// | [000..032) | tips      | uint256 | 32    | Encoded tips paid on origin chain      |\n/// | [032..064) | sender    | bytes32 | 32    | Sender address on origin chain         |\n/// | [064..096) | recipient | bytes32 | 32    | Recipient address on destination chain |\n/// | [096..116) | request   | uint160 | 20    | Encoded request for message execution  |\n/// | [104..AAA) | content   | bytes   | ??    | Content to be passed to recipient      |\nlibrary BaseMessageLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_TIPS = 0;\n    uint256 private constant OFFSET_SENDER = 32;\n    uint256 private constant OFFSET_RECIPIENT = 64;\n    uint256 private constant OFFSET_REQUEST = OFFSET_RECIPIENT + TIPS_LENGTH;\n    uint256 private constant OFFSET_CONTENT = OFFSET_REQUEST + REQUEST_LENGTH;\n\n    // ═══════════════════════════════════════════════ BASE MESSAGE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted BaseMessage payload with provided fields.\n     * @param tips_         Encoded tips information\n     * @param sender_       Sender address on origin chain\n     * @param recipient_    Recipient address on destination chain\n     * @param request_      Encoded request for message execution\n     * @param content_      Raw content to be passed to recipient on destination chain\n     * @return Formatted base message\n     */\n    function formatBaseMessage(Tips tips_, bytes32 sender_, bytes32 recipient_, Request request_, bytes memory content_)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return abi.encodePacked(tips_, sender_, recipient_, request_, content_);\n    }\n\n    /**\n     * @notice Returns a BaseMessage view over the given payload.\n     * @dev Will revert if the payload is not a base message.\n     */\n    function castToBaseMessage(bytes memory payload) internal pure returns (BaseMessage) {\n        return castToBaseMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a BaseMessage view.\n     * @dev Will revert if the memory view is not over a base message payload.\n     */\n    function castToBaseMessage(MemView memView) internal pure returns (BaseMessage) {\n        if (!isBaseMessage(memView)) revert UnformattedBaseMessage();\n        return BaseMessage.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted BaseMessage.\n    function isBaseMessage(MemView memView) internal pure returns (bool) {\n        // Check if sender, recipient, tips fields exist\n        return (memView.len() \u003e= OFFSET_CONTENT);\n        // Content could be empty, so we don't check that\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(BaseMessage baseMessage) internal pure returns (MemView) {\n        return MemView.wrap(BaseMessage.unwrap(baseMessage));\n    }\n\n    /// @notice Returns baseMessage's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        // We hash \"tips\" and \"everything but tips\" to make tips proofs easier to verify\n        return MerkleMath.getParent(baseMessage.tips().leaf(), baseMessage.bodyLeaf());\n    }\n\n    /// @notice Returns hash for the \"everything but tips\" part of the base message.\n    function bodyLeaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_SENDER}).keccak();\n    }\n\n    // ═══════════════════════════════════════════ BASE MESSAGE SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips paid on origin chain.\n    function tips(BaseMessage baseMessage) internal pure returns (Tips) {\n        return TipsLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_TIPS, bytes_: TIPS_LENGTH})));\n    }\n\n    /// @notice Returns sender address on origin chain.\n    function sender(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_SENDER, bytes_: 32});\n    }\n\n    /// @notice Returns recipient address on destination chain.\n    function recipient(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_RECIPIENT, bytes_: 32});\n    }\n\n    /// @notice Returns an encoded request for message execution on destination chain.\n    function request(BaseMessage baseMessage) internal pure returns (Request) {\n        return RequestLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_REQUEST, bytes_: REQUEST_LENGTH})));\n    }\n\n    /// @notice Returns an untyped memory view over the content to be passed to recipient.\n    function content(BaseMessage baseMessage) internal pure returns (MemView) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_CONTENT});\n    }\n}\n\n// contracts/base/MessagingBase.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for all messaging contracts.\n * - Provides context on the local chain's domain.\n * - Provides ownership functionality.\n * - Will be providing pausing functionality when it is implemented.\n */\nabstract contract MessagingBase is MultiCallable, Versioned, Ownable2StepUpgradeable {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @notice Domain of the local chain, set once upon contract creation\n    uint32 public immutable localDomain;\n    // @notice Domain of the Synapse chain, set once upon contract creation\n    uint32 public immutable synapseDomain;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev gap for upgrade safety\n    uint256[50] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    constructor(string memory version_, uint32 synapseDomain_) Versioned(version_) {\n        localDomain = ChainContext.chainId();\n        synapseDomain = synapseDomain_;\n    }\n\n    // TODO: Implement pausing\n\n    /**\n     * @dev Should be impossible to renounce ownership;\n     * we override OpenZeppelin OwnableUpgradeable's\n     * implementation of renounceOwnership to make it a no-op\n     */\n    function renounceOwnership() public override onlyOwner {} //solhint-disable-line no-empty-blocks\n}\n\n// contracts/libs/memory/Message.sol\n\n/// Message is a memory over over a formatted message payload.\ntype Message is uint256;\n\nusing MessageLib for Message global;\n\n/// Library for formatting the various messages supported by Origin and Destination.\n///\n/// # Message memory layout\n///\n/// | Position   | Field  | Type    | Bytes | Description                                             |\n/// | ---------- | ------ | ------- | ----- | ------------------------------------------------------- |\n/// | [000..017) | header | uint136 | 17    | Encoded general routing information for the message     |\n/// | [017..AAA) | body   | bytes   | ??    | Formatted payload (according to flag) with message body |\nlibrary MessageLib {\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MemViewLib for bytes;\n    using HeaderLib for MemView;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_HEADER = 0;\n    uint256 private constant OFFSET_BODY = OFFSET_HEADER + HEADER_LENGTH;\n\n    // ══════════════════════════════════════════════════ MESSAGE ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns formatted message with provided fields.\n     * @param header_   Encoded general routing information for the message\n     * @param body_     Formatted payload (according to flag) with message body\n     * @return Formatted message\n     */\n    function formatMessage(Header header_, bytes memory body_) internal pure returns (bytes memory) {\n        return abi.encodePacked(header_, body_);\n    }\n\n    /**\n     * @notice Returns a Message view over for the given payload.\n     * @dev Will revert if the payload is not a message payload.\n     */\n    function castToMessage(bytes memory payload) internal pure returns (Message) {\n        return castToMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Message view.\n     * @dev Will revert if the memory view is not over a message payload.\n     */\n    function castToMessage(MemView memView) internal pure returns (Message) {\n        if (!isMessage(memView)) revert UnformattedMessage();\n        return Message.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Message.\n     */\n    function isMessage(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Check if headers exist in the payload\n        if (length \u003c OFFSET_BODY) return false;\n        // Check that Header is valid\n        uint256 paddedHeader = _header(memView);\n        if (!HeaderLib.isHeader(paddedHeader)) return false;\n        // Check that body is formatted according to the flag\n        // Only Base/Manager message flags exist\n        if (HeaderLib.wrapPadded(paddedHeader).flag() == MessageFlag.Base) {\n            // Check if body is a formatted base message\n            return _body(memView).isBaseMessage();\n        } else {\n            // Check if body is a formatted calldata for AgentManager call\n            return _body(memView).isCallData();\n        }\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Message message) internal pure returns (MemView) {\n        return MemView.wrap(Message.unwrap(message));\n    }\n\n    /// @notice Returns message's hash: a leaf to be inserted in the Merkle tree.\n    function leaf(Message message) internal pure returns (bytes32) {\n        // We hash header and body separately to make message proofs easier to verify\n        Header header_ = message.header();\n        // Only Base/Manager message flags exist\n        if (header_.flag() == MessageFlag.Base) {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToBaseMessage().leaf());\n        } else {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToCallData().leaf());\n        }\n    }\n\n    // ══════════════════════════════════════════════ MESSAGE SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns message's encoded header field.\n    function header(Message message) internal pure returns (Header) {\n        return HeaderLib.wrapPadded((message.unwrap().indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH})));\n    }\n\n    /// @notice Returns message's body field as an untyped memory view.\n    function body(Message message) internal pure returns (MemView) {\n        MemView memView = message.unwrap();\n        return _body(memView);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns message's padded header without checking that it is a valid header.\n    function _header(MemView memView) private pure returns (uint256) {\n        return memView.indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH});\n    }\n\n    /// @dev Returns an untyped memory view over the body field without checking\n    /// if the whole payload or the body are properly formatted.\n    function _body(MemView memView) private pure returns (MemView) {\n        return memView.sliceFrom({index_: OFFSET_BODY});\n    }\n}\n\n// contracts/base/AgentSecured.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for messaging contracts that are secured by the agent manager.\n * `AgentSecured` relies on `AgentManager` to provide the following functionality:\n * - Keep track of agents and their statuses.\n * - Pass agent-signed statements that were verified by the agent manager.\n * - These statements are considered valid indefinitely, unless the agent is disputed.\n * - Disputes are opened and resolved by the agent manager.\n * \u003e `AgentSecured` implementation should never use statements signed by agents that are disputed.\n */\nabstract contract AgentSecured is MessagingBase, IAgentSecured {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    address public immutable agentManager;\n\n    /// @inheritdoc IAgentSecured\n    address public immutable inbox;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    // (agent index =\u003e their dispute status: flag, openedAt, resolvedAt)\n    mapping(uint32 =\u003e DisputeStatus) internal _disputes;\n\n    /// @dev gap for upgrade safety\n    uint256[49] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    modifier onlyAgentManager() {\n        if (msg.sender != agentManager) revert CallerNotAgentManager();\n        _;\n    }\n\n    modifier onlyInbox() {\n        if (msg.sender != inbox) revert CallerNotInbox();\n        _;\n    }\n\n    constructor(string memory version_, uint32 synapseDomain_, address agentManager_, address inbox_)\n        MessagingBase(version_, synapseDomain_)\n    {\n        agentManager = agentManager_;\n        inbox = inbox_;\n    }\n\n    // ════════════════════════════════════════════ ONLY AGENT MANAGER ═════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external onlyAgentManager {\n        uint40 openedAt = ChainContext.blockTimestamp();\n        DisputeStatus memory status = DisputeStatus({flag: DisputeFlag.Pending, openedAt: openedAt, resolvedAt: 0});\n        _disputes[guardIndex] = status;\n        _disputes[notaryIndex] = status;\n    }\n\n    /// @inheritdoc IAgentSecured\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external onlyAgentManager {\n        // Update the dispute status of the slashed agent first.\n        uint40 resolvedAt = ChainContext.blockTimestamp();\n        _disputes[slashedIndex].flag = DisputeFlag.Slashed;\n        _disputes[slashedIndex].resolvedAt = resolvedAt;\n        // Mark the rival agent as not disputed, if there was an ongoing dispute.\n        if (rivalIndex != 0) {\n            _disputes[rivalIndex].flag = DisputeFlag.None;\n            _disputes[rivalIndex].resolvedAt = resolvedAt;\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function agentStatus(address agent) external view returns (AgentStatus memory) {\n        return _agentStatus(agent);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status) {\n        return _getAgent(index);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory) {\n        return _disputes[agentIndex];\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns status of the given agent: (flag, domain, index).\n    function _agentStatus(address agent) internal view returns (AgentStatus memory) {\n        return IAgentManager(agentManager).agentStatus(agent);\n    }\n\n    /// @dev Returns agent and their status for a given agent index. Returns zero values for non existing indexes.\n    function _getAgent(uint256 index) internal view returns (address agent, AgentStatus memory status) {\n        return IAgentManager(agentManager).getAgent(index);\n    }\n\n    /// @dev Checks if a Dispute exists for the given Notary. This function returns true, if\n    /// Notary is in ongoing Dispute, or if Dispute was resolved not in Notary's favor.\n    /// In both cases we can't trust Notary's data.\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeExists(uint32 notaryIndex) internal view returns (bool) {\n        return _disputes[notaryIndex].flag != DisputeFlag.None;\n    }\n\n    /// @dev Checks if a Notary recently won a Dispute and is still in the \"post-dispute\" timeout period.\n    /// In this period we still can't trust Notary's data, though we can optimistically assume that\n    /// that the data will be correct after the timeout (assuming no new Disputes are opened).\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeTimeout(uint32 notaryIndex) internal view returns (bool) {\n        DisputeStatus memory status = _disputes[notaryIndex];\n        // Exit early if Notary is in ongoing Dispute / slashed.\n        if (status.flag != DisputeFlag.None) return false;\n        // Check if Notary has been in any Dispute at all.\n        if (status.openedAt == 0) return false;\n        // Otherwise check if the Dispute timeout is still active.\n        return block.timestamp \u003c status.resolvedAt + DISPUTE_TIMEOUT_NOTARY;\n    }\n}\n\n// contracts/hubs/StateHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StateHub` is a parent contract for `Origin`. It is responsible for the following:\n/// - Keeping track of the historical Origin Merkle Tree containing all the message hashes.\n/// - Keeping track of the historical Origin States, as well as verifying their validity.\nabstract contract StateHub is AgentSecured, StateHubEvents, IStateHub {\n    using SafeCast for uint256;\n    using StateLib for bytes;\n\n    struct OriginState {\n        uint40 blockNumber;\n        uint40 timestamp;\n        GasData gasData;\n    }\n    // Bits left for tight packing: 80\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Historical Merkle Tree\n    /// Note: Takes two storage slots\n    HistoricalTree private _tree;\n\n    /// @dev All historical contract States\n    OriginState[] private _originStates;\n\n    /// @dev gap for upgrade safety\n    uint256[47] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IStateHub\n    function isValidState(bytes memory statePayload) external view returns (bool isValid) {\n        // This will revert if payload is not a formatted state\n        State state = statePayload.castToState();\n        return _isValidState(state);\n    }\n\n    /// @inheritdoc IStateHub\n    function statesAmount() external view returns (uint256) {\n        return _originStates.length;\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestLatestState() external view returns (bytes memory stateData) {\n        // This never underflows, assuming the contract was initialized\n        return suggestState(_nextNonce() - 1);\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestState(uint32 nonce) public view returns (bytes memory stateData) {\n        // This will revert if nonce is out of range\n        bytes32 root = _tree.root(nonce);\n        return _formatOriginState(_originStates[nonce], root, localDomain, nonce);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Initializes the saved states list by inserting a state for an empty Merkle Tree.\n    function _initializeStates() internal {\n        // This should only be called once, when the contract is initialized\n        // This will revert if _tree.roots is non-empty\n        bytes32 savedRoot = _tree.initializeRoots();\n        // Save root for empty merkle _tree with block number and timestamp of initialization\n        _saveState(savedRoot, _toOriginState());\n    }\n\n    /// @dev Inserts leaf into the Merkle Tree and saves the updated origin State.\n    function _insertAndSave(bytes32 leaf) internal {\n        bytes32 newRoot = _tree.insert(leaf);\n        _saveState(newRoot, _toOriginState());\n    }\n\n    /// @dev Saves an updated state of the Origin contract\n    function _saveState(bytes32 root, OriginState memory state) internal {\n        uint32 nonce = _nextNonce();\n        _originStates.push(state);\n        // Emit event with raw state data\n        emit StateSaved(_formatOriginState(state, root, localDomain, nonce));\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns nonce of the next sent message: the amount of saved States so far.\n    /// This always equals to \"total amount of sent messages\" plus 1.\n    function _nextNonce() internal view returns (uint32) {\n        // TODO: consider using more than 32 bits for origin nonces\n        return _originStates.length.toUint32();\n    }\n\n    /// @dev Checks if a state is valid, i.e. if it matches the historical one.\n    /// Reverts, if state refers to another Origin contract.\n    function _isValidState(State state) internal view returns (bool) {\n        // Check if state refers to this contract\n        if (state.origin() != localDomain) revert IncorrectOriginDomain();\n        // Check if nonce exists\n        uint32 nonce = state.nonce();\n        if (nonce \u003e= _originStates.length) return false;\n        // Check if state root matches the historical one\n        if (state.root() != _tree.root(nonce)) return false;\n        // Check if state metadata matches the historical one\n        return _areEqual(state, _originStates[nonce]);\n    }\n\n    // ═════════════════════════════════════════════ STRUCT FORMATTING ═════════════════════════════════════════════════\n\n    /// @dev Returns a formatted payload for a stored OriginState.\n    function _formatOriginState(OriginState memory originState, bytes32 root, uint32 origin, uint32 nonce)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return StateLib.formatState({\n            root_: root,\n            origin_: origin,\n            nonce_: nonce,\n            blockNumber_: originState.blockNumber,\n            timestamp_: originState.timestamp,\n            gasData_: originState.gasData\n        });\n    }\n\n    /// @dev Child contract should implement the logic for getting the current gas data from the gas oracle\n    /// to be saved as part of the Origin State.\n    // solhint-disable-next-line ordering\n    function _fetchGasData() internal view virtual returns (GasData);\n\n    /// @dev Returns a OriginState struct to save in the contract.\n    function _toOriginState() internal view returns (OriginState memory originState) {\n        originState.blockNumber = ChainContext.blockNumber();\n        originState.timestamp = ChainContext.blockTimestamp();\n        originState.gasData = _fetchGasData();\n    }\n\n    /// @dev Checks that a state and its Origin representation are equal.\n    function _areEqual(State state, OriginState memory originState) internal pure returns (bool) {\n        return state.blockNumber() == originState.blockNumber \u0026\u0026 state.timestamp() == originState.timestamp;\n    }\n}\n\n// contracts/Origin.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Origin` contract is used for sending messages to remote chains. It is done\n/// by inserting the message hashes into the Origin Merkle, which makes it possible to\n/// prove that message was sent using the Merkle proof against the Origin Merkle Root. This essentially\n/// compresses the list of messages into a single 32-byte value that needs to be stored on the destination chain.\n/// `Origin` is responsible for the following:\n/// - Formatting the sent message payloads, and inserting their hashes into the Origin Merkle Tree.\n/// - Keeping track of its own historical states (see parent contract `StateHub`).\n/// - Enforcing minimum tip values for sent base messages based on the provided execution requests.\n/// - Distributing the collected tips upon request from a local `AgentManager` contract.\ncontract Origin is StateHub, OriginEvents, InterfaceOrigin {\n    using MemViewLib for bytes;\n    using MessageLib for bytes;\n    using TipsLib for bytes;\n    using TypeCasts for address;\n\n    address public immutable gasOracle;\n\n    modifier onlyRemoteDestination(uint32 destination) {\n        if (destination == localDomain) revert IncorrectDestinationDomain();\n        _;\n    }\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_, address gasOracle_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {\n        gasOracle = gasOracle_;\n    }\n\n    /// @notice Initializes Origin contract:\n    /// - msg.sender is set as contract owner\n    /// - State of \"empty merkle tree\" is saved\n    function initialize() external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize \"states\": state of an \"empty merkle tree\" is saved\n        _initializeStates();\n    }\n\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable onlyRemoteDestination(destination) returns (uint32 messageNonce, bytes32 messageHash) {\n        // Check that content is not too large\n        if (content.length \u003e MAX_CONTENT_BYTES) revert ContentLengthTooBig();\n        // This will revert if msg.value is lower than value of minimum tips\n        Tips tips = _getMinimumTips(destination, paddedRequest, content.length).matchValue(msg.value);\n        Request request = RequestLib.wrapPadded(paddedRequest);\n        // Format the BaseMessage body\n        bytes memory body = BaseMessageLib.formatBaseMessage({\n            sender_: msg.sender.addressToBytes32(),\n            recipient_: recipient,\n            tips_: tips,\n            request_: request,\n            content_: content\n        });\n        // Send the message\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Base, body);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        onlyAgentManager\n        onlyRemoteDestination(destination)\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // AgentManager (checked via modifier) is responsible for constructing the calldata payload correctly.\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Manager, payload);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function withdrawTips(address recipient, uint256 amount) external onlyAgentManager {\n        if (address(this).balance \u003c amount) revert InsufficientEthBalance();\n        (bool success,) = recipient.call{value: amount}(\"\");\n        if (!success) revert EthTransferFailed();\n        emit TipWithdrawalCompleted(recipient, amount);\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue)\n    {\n        return _getMinimumTips(destination, paddedRequest, contentLength).value();\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Sends the given message to the specified destination. Message hash is inserted\n    /// into the Origin Merkle Tree, which will enable message execution on destination chain.\n    function _sendMessage(uint32 destination, uint32 optimisticPeriod, MessageFlag flag, bytes memory body)\n        internal\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // Format the message header\n        messageNonce = _nextNonce();\n        Header header = flag.encodeHeader({\n            origin_: localDomain,\n            nonce_: messageNonce,\n            destination_: destination,\n            optimisticPeriod_: optimisticPeriod\n        });\n        // Format the full message payload\n        bytes memory msgPayload = MessageLib.formatMessage(header, body);\n        // Insert new leaf into the Origin Merkle Tree and save the updated state\n        messageHash = msgPayload.castToMessage().leaf();\n        _insertAndSave(messageHash);\n        // Emit event with message information\n        emit Sent(messageHash, messageNonce, destination, msgPayload);\n        // Update the gas oracle data. We do this after the provided tips are checked so that\n        // the provided message is sent in the event that the gas oracle data is updated to a higher value.\n        InterfaceGasOracle(gasOracle).updateGasData(destination);\n        // TODO: consider doing this before the message is sent, while adjusting GasOracle.getMinimumTips() to\n        // use the pending gas oracle data.\n    }\n\n    /// @dev Returns the minimum tips for sending a message to the given destination with the given request and content.\n    function _getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        internal\n        view\n        returns (Tips)\n    {\n        return\n            TipsLib.wrapPadded(InterfaceGasOracle(gasOracle).getMinimumTips(destination, paddedRequest, contentLength));\n    }\n\n    /// @dev Gets the current gas data from the gas oracle to be saved as part of the Origin State.\n    function _fetchGasData() internal view override returns (GasData) {\n        return GasDataLib.wrapGasData(InterfaceGasOracle(gasOracle).getGasData());\n    }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"102473:9845:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;102473:9845:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"102473:9845:0:-:0;;;;;;;;","abiDefinition":[],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Origin.sol\":\"MerkleMath\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Origin.sol\":{\"keccak256\":\"0x96775924f147f3d1f8df8cdf56731fe52a15af8d8e12e608efb8158c112b18cd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e642a27f5fab3c62b4c02e9754e9e42b1cf2e5381dbea9d3d106d23b7772ebe6\",\"dweb:/ipfs/QmUwn7ZyBvPkjnMuK8ZMSexBUdNQnVtxwyoAyT4DXLQjra\"]}},\"version\":1}"},"hashes":{}},"solidity/Origin.sol:MerkleTree":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122074376a2a1e9b53567a1b3bba9524b760eec2c1fe88891752acad8c79f7f2149764736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122074376a2a1e9b53567a1b3bba9524b760eec2c1fe88891752acad8c79f7f2149764736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/OriginEvents.sol\n\n/// @notice A collection of events emitted by the Origin contract\nabstract contract OriginEvents {\n    /**\n     * @notice Emitted when a new message is sent.\n     * @param messageHash   Hash of message; the leaf inserted to the Merkle tree for the message\n     * @param nonce         Nonce of sent message (starts from 1)\n     * @param destination   Destination domain\n     * @param message       Raw bytes of message\n     */\n    event Sent(bytes32 indexed messageHash, uint32 indexed nonce, uint32 indexed destination, bytes message);\n\n    /**\n     * @notice Emitted when a tip withdrawal is completed.\n     * @param actor     Actor address\n     * @param tip       Tip value, denominated in local domain's wei\n     */\n    event TipWithdrawalCompleted(address actor, uint256 tip);\n}\n\n// contracts/events/StateHubEvents.sol\n\n/// @notice A collection of events emitted by the StateHub contract\nabstract contract StateHubEvents {\n    /**\n     * @notice Emitted when a new Origin State is saved after a message was sent.\n     * @param state     Raw payload with state data\n     */\n    event StateSaved(bytes state);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n    /**\n     * @notice Check that a given state is valid: matches the historical state of Origin contract.\n     * Note: any Agent including an invalid state in their snapshot will be slashed\n     * upon providing the snapshot and agent signature for it to Origin contract.\n     * @dev Will revert if any of these is true:\n     *  - State payload is not properly formatted.\n     * @param statePayload      Raw payload with state data\n     * @return isValid          Whether the provided state is valid\n     */\n    function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns the amount of saved states so far.\n     * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n     */\n    function statesAmount() external view returns (uint256);\n\n    /**\n     * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @return statePayload     Raw payload with the latest state data\n     */\n    function suggestLatestState() external view returns (bytes memory statePayload);\n\n    /**\n     * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @param nonce             Historical nonce to form a state\n     * @return statePayload     Raw payload with historical state data\n     */\n    function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/InterfaceGasOracle.sol\n\ninterface InterfaceGasOracle {\n    /**\n     * @notice Fetches the latest gas data for the chain from `Destination` contract,\n     * and uses it to update the oracle values for the requested chain.\n     * @param domain    Domain to update the gas data for\n     */\n    function updateGasData(uint32 domain) external;\n\n    /**\n     * @notice Returns the gas data for the local chain.\n     */\n    function getGasData() external view returns (uint256 paddedGasData);\n\n    /**\n     * @notice Returns the gas data for the given domain, in the decoded format.\n     * @param domain        Domain of chain to get gas data for\n     * @return gasPrice     Gas price for the chain (in Wei per gas unit)\n     * @return dataPrice    Calldata price (in Wei per byte of content)\n     * @return execBuffer   Tx fee safety buffer for message execution (in Wei)\n     * @return amortAttCost Amortized cost for attestation submission (in Wei)\n     * @return etherPrice   Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n     * @return markup       Markup for the message execution (in BWAD)\n     */\n    function getDecodedGasData(uint32 domain)\n        external\n        view\n        returns (\n            uint256 gasPrice,\n            uint256 dataPrice,\n            uint256 execBuffer,\n            uint256 amortAttCost,\n            uint256 etherPrice,\n            uint256 markup\n        );\n\n    /**\n     * @notice Returns the minimum tips for sending a message to a given destination.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return paddedTips       Padded encoded minimum tips information\n     */\n    function getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 paddedTips);\n}\n\n// contracts/interfaces/InterfaceOrigin.sol\n\ninterface InterfaceOrigin {\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /**\n     * @notice Send a message to the recipient located on destination domain.\n     * @dev Recipient has to conform to IMessageRecipient interface, otherwise message won't be delivered.\n     * Will revert if any of these is true:\n     * - `destination` is equal to contract's local domain\n     * - `content` length is greater than `MAX_CONTENT_BYTES`\n     * - `msg.value` is lower than value of minimum tips for the given message\n     * @param destination           Domain of destination chain\n     * @param recipient             Address of recipient on destination chain as bytes32\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param paddedRequest         Padded encoded message execution request on destination chain\n     * @param content               Raw bytes content of message\n     * @return messageNonce         Nonce of the sent message\n     * @return messageHash          Hash of the sent message\n     */\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable returns (uint32 messageNonce, bytes32 messageHash);\n\n    /**\n     * @notice Send a manager message to the destination domain.\n     * @dev This could only be called by AgentManager, which takes care of encoding the calldata payload.\n     * Note: (msgOrigin, proofMaturity) security args will be added to payload on the destination chain\n     * so that the AgentManager could verify where the Manager Message came from and how mature is the proof.\n     * Note: function is not payable, as no tips are required for sending a manager message.\n     * Will revert if `destination` is equal to contract's local domain.\n     * @param destination           Domain of destination chain\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param payload               Payload for calling AgentManager on destination chain (with extra security args)\n     */\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        returns (uint32 messageNonce, bytes32 messageHash);\n\n    // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Withdraws locked base message tips to the recipient.\n     * @dev Could only be called by a local AgentManager.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function withdrawTips(address recipient, uint256 amount) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the minimum tips value for sending a message to a given destination.\n     * @dev Using at least `tipsValue` as `msg.value` for `sendBaseMessage()`\n     * will guarantee that the message will be accepted.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return tipsValue        Minimum tips value for a message to be accepted\n     */\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue);\n}\n\n// contracts/libs/Constants.sol\n\n// Here we define common constants to enable their easier reusing later.\n\n// ══════════════════════════════════ MERKLE ═══════════════════════════════════\n/// @dev Height of the Agent Merkle Tree\nuint256 constant AGENT_TREE_HEIGHT = 32;\n/// @dev Height of the Origin Merkle Tree\nuint256 constant ORIGIN_TREE_HEIGHT = 32;\n/// @dev Height of the Snapshot Merkle Tree. Allows up to 64 leafs, e.g. up to 32 states\nuint256 constant SNAPSHOT_TREE_HEIGHT = 6;\n// ══════════════════════════════════ STRUCTS ══════════════════════════════════\n/// @dev See Attestation.sol: (bytes32,bytes32,uint32,uint40,uint40): 32+32+4+5+5\nuint256 constant ATTESTATION_LENGTH = 78;\n/// @dev See GasData.sol: (uint16,uint16,uint16,uint16,uint16,uint16): 2+2+2+2+2+2\nuint256 constant GAS_DATA_LENGTH = 12;\n/// @dev See Receipt.sol: (uint32,uint32,bytes32,bytes32,uint8,address,address,address): 4+4+32+32+1+20+20+20\nuint256 constant RECEIPT_LENGTH = 133;\n/// @dev See State.sol: (bytes32,uint32,uint32,uint40,uint40,GasData): 32+4+4+5+5+len(GasData)\nuint256 constant STATE_LENGTH = 50 + GAS_DATA_LENGTH;\n/// @dev Maximum amount of states in a single snapshot. Each state produces two leafs in the tree\nuint256 constant SNAPSHOT_MAX_STATES = 1 \u003c\u003c (SNAPSHOT_TREE_HEIGHT - 1);\n// ══════════════════════════════════ MESSAGE ══════════════════════════════════\n/// @dev See Header.sol: (uint8,uint32,uint32,uint32,uint32): 1+4+4+4+4\nuint256 constant HEADER_LENGTH = 17;\n/// @dev See Request.sol: (uint96,uint64,uint32): 12+8+4\nuint256 constant REQUEST_LENGTH = 24;\n/// @dev See Tips.sol: (uint64,uint64,uint64,uint64): 8+8+8+8\nuint256 constant TIPS_LENGTH = 32;\n/// @dev The amount of discarded last bits when encoding tip values\nuint256 constant TIPS_GRANULARITY = 32;\n/// @dev Tip values could be only the multiples of TIPS_MULTIPLIER\nuint256 constant TIPS_MULTIPLIER = 1 \u003c\u003c TIPS_GRANULARITY;\n// ══════════════════════════════ STATEMENT SALTS ══════════════════════════════\n/// @dev Salts for signing various statements\nbytes32 constant ATTESTATION_VALID_SALT = keccak256(\"ATTESTATION_VALID_SALT\");\nbytes32 constant ATTESTATION_INVALID_SALT = keccak256(\"ATTESTATION_INVALID_SALT\");\nbytes32 constant RECEIPT_VALID_SALT = keccak256(\"RECEIPT_VALID_SALT\");\nbytes32 constant RECEIPT_INVALID_SALT = keccak256(\"RECEIPT_INVALID_SALT\");\nbytes32 constant SNAPSHOT_VALID_SALT = keccak256(\"SNAPSHOT_VALID_SALT\");\nbytes32 constant STATE_INVALID_SALT = keccak256(\"STATE_INVALID_SALT\");\n// ═════════════════════════════════ PROTOCOL ══════════════════════════════════\n/// @dev Optimistic period for new agent roots in LightManager\nuint32 constant AGENT_ROOT_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Timeout between the agent root could be proposed and resolved in LightManager\nuint32 constant AGENT_ROOT_PROPOSAL_TIMEOUT = 12 hours;\nuint32 constant BONDING_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Amount of time that the Notary will not be considered active after they won a dispute\nuint32 constant DISPUTE_TIMEOUT_NOTARY = 12 hours;\n/// @dev Amount of time without fresh data from Notaries before contract owner can resolve stuck disputes manually\nuint256 constant FRESH_DATA_TIMEOUT = 4 hours;\n/// @dev Maximum bytes per message = 2 KiB (somewhat arbitrarily set to begin)\nuint256 constant MAX_CONTENT_BYTES = 2 * 2 ** 10;\n/// @dev Maximum value for the summit tip that could be set in GasOracle\nuint256 constant MAX_SUMMIT_TIP = 0.01 ether;\n\n// contracts/libs/Errors.sol\n\n// ══════════════════════════════ INVALID CALLER ═══════════════════════════════\n\nerror CallerNotAgentManager();\nerror CallerNotDestination();\nerror CallerNotInbox();\nerror CallerNotSummit();\n\n// ══════════════════════════════ INCORRECT DATA ═══════════════════════════════\n\nerror IncorrectAttestation();\nerror IncorrectAgentDomain();\nerror IncorrectAgentIndex();\nerror IncorrectAgentProof();\nerror IncorrectAgentRoot();\nerror IncorrectDataHash();\nerror IncorrectDestinationDomain();\nerror IncorrectOriginDomain();\nerror IncorrectSnapshotProof();\nerror IncorrectSnapshotRoot();\nerror IncorrectState();\nerror IncorrectStatesAmount();\nerror IncorrectTipsProof();\nerror IncorrectVersionLength();\n\nerror IncorrectNonce();\nerror IncorrectSender();\nerror IncorrectRecipient();\n\nerror FlagOutOfRange();\nerror IndexOutOfRange();\nerror NonceOutOfRange();\n\nerror OutdatedNonce();\n\nerror UnformattedAttestation();\nerror UnformattedAttestationReport();\nerror UnformattedBaseMessage();\nerror UnformattedCallData();\nerror UnformattedCallDataPrefix();\nerror UnformattedMessage();\nerror UnformattedReceipt();\nerror UnformattedReceiptReport();\nerror UnformattedSignature();\nerror UnformattedSnapshot();\nerror UnformattedState();\nerror UnformattedStateReport();\n\n// ═══════════════════════════════ MERKLE TREES ════════════════════════════════\n\nerror LeafNotProven();\nerror MerkleTreeFull();\nerror NotEnoughLeafs();\nerror TreeHeightTooLow();\n\n// ═════════════════════════════ OPTIMISTIC PERIOD ═════════════════════════════\n\nerror BaseClientOptimisticPeriod();\nerror MessageOptimisticPeriod();\nerror SlashAgentOptimisticPeriod();\nerror WithdrawTipsOptimisticPeriod();\nerror ZeroProofMaturity();\n\n// ═══════════════════════════════ AGENT MANAGER ═══════════════════════════════\n\nerror AgentNotGuard();\nerror AgentNotNotary();\n\nerror AgentCantBeAdded();\nerror AgentNotActive();\nerror AgentNotActiveNorUnstaking();\nerror AgentNotFraudulent();\nerror AgentNotUnstaking();\nerror AgentUnknown();\n\nerror AgentRootNotProposed();\nerror AgentRootTimeoutNotOver();\n\nerror NotStuck();\n\nerror DisputeAlreadyResolved();\nerror DisputeNotOpened();\nerror DisputeTimeoutNotOver();\nerror GuardInDispute();\nerror NotaryInDispute();\n\nerror MustBeSynapseDomain();\nerror SynapseDomainForbidden();\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\nerror AlreadyExecuted();\nerror AlreadyFailed();\nerror DuplicatedSnapshotRoot();\nerror IncorrectMagicValue();\nerror GasLimitTooLow();\nerror GasSuppliedTooLow();\n\n// ══════════════════════════════════ ORIGIN ═══════════════════════════════════\n\nerror ContentLengthTooBig();\nerror EthTransferFailed();\nerror InsufficientEthBalance();\n\n// ════════════════════════════════ GAS ORACLE ═════════════════════════════════\n\nerror LocalGasDataNotSet();\nerror RemoteGasDataNotSet();\n\n// ═══════════════════════════════════ TIPS ════════════════════════════════════\n\nerror SummitTipTooHigh();\nerror TipsClaimMoreThanEarned();\nerror TipsClaimZero();\nerror TipsOverflow();\nerror TipsValueTooLow();\n\n// ════════════════════════════════ MEMORY VIEW ════════════════════════════════\n\nerror IndexedTooMuch();\nerror ViewOverrun();\nerror OccupiedMemory();\nerror UnallocatedMemory();\nerror PrecompileOutOfGas();\n\n// ═════════════════════════════════ MULTICALL ═════════════════════════════════\n\nerror MulticallFailed();\n\n// contracts/libs/TypeCasts.sol\n\nlibrary TypeCasts {\n    // alignment preserving cast\n    function addressToBytes32(address addr) internal pure returns (bytes32) {\n        return bytes32(uint256(uint160(addr)));\n    }\n\n    // alignment preserving cast\n    function bytes32ToAddress(bytes32 buf) internal pure returns (address) {\n        return address(uint160(uint256(buf)));\n    }\n}\n\n// contracts/libs/stack/Number.sol\n\n/// Number is a compact representation of uint256, that is fit into 16 bits\n/// with the maximum relative error under 0.4%.\ntype Number is uint16;\n\nusing NumberLib for Number global;\n\n/// # Number\n/// Library for compact representation of uint256 numbers.\n/// - Number is stored using mantissa and exponent, each occupying 8 bits.\n/// - Numbers under 2**8 are stored as `mantissa` with `exponent = 0xFF`.\n/// - Numbers at least 2**8 are approximated as `(256 + mantissa) \u003c\u003c exponent`\n/// \u003e - `0 \u003c= mantissa \u003c 256`\n/// \u003e - `0 \u003c= exponent \u003c= 247` (`256 * 2**248` doesn't fit into uint256)\n/// # Number stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type  | Bytes |\n/// | ---------- | -------- | ----- | ----- |\n/// | (002..001] | mantissa | uint8 | 1     |\n/// | (001..000] | exponent | uint8 | 1     |\n\nlibrary NumberLib {\n    /// @dev Amount of bits to shift to mantissa field\n    uint16 private constant SHIFT_MANTISSA = 8;\n\n    /// @notice For bwad math (binary wad) we use 2**64 as \"wad\" unit.\n    /// @dev We are using not using 10**18 as wad, because it is not stored precisely in NumberLib.\n    uint256 internal constant BWAD_SHIFT = 64;\n    uint256 internal constant BWAD = 1 \u003c\u003c BWAD_SHIFT;\n    /// @notice ~0.1% in bwad units.\n    uint256 internal constant PER_MILLE_SHIFT = BWAD_SHIFT - 10;\n    uint256 internal constant PER_MILLE = 1 \u003c\u003c PER_MILLE_SHIFT;\n\n    /// @notice Compresses uint256 number into 16 bits.\n    function compress(uint256 value) internal pure returns (Number) {\n        // Find `msb` such as `2**msb \u003c= value \u003c 2**(msb + 1)`\n        uint256 msb = mostSignificantBit(value);\n        // We want to preserve 9 bits of precision.\n        // The highest bit is always 1, so we can skip it.\n        // The remaining 8 highest bits are stored as mantissa.\n        if (msb \u003c 8) {\n            // Value is less than 2**8, so we can use value as mantissa with \"-1\" exponent.\n            return _encode(uint8(value), 0xFF);\n        } else {\n            // We use `msb - 8` as exponent otherwise. Note that `exponent \u003e= 0`.\n            unchecked {\n                uint256 exponent = msb - 8;\n                // Shifting right by `msb-8` bits will shift the \"remaining 8 highest bits\" into the 8 lowest bits.\n                // uint8() will truncate the highest bit.\n                return _encode(uint8(value \u003e\u003e exponent), uint8(exponent));\n            }\n        }\n    }\n\n    /// @notice Decompresses 16 bits number into uint256.\n    /// @dev The outcome is an approximation of the original number: `(value - value / 256) \u003c number \u003c= value`.\n    function decompress(Number number) internal pure returns (uint256 value) {\n        // Isolate 8 highest bits as the mantissa.\n        uint256 mantissa = Number.unwrap(number) \u003e\u003e SHIFT_MANTISSA;\n        // This will truncate the highest bits, leaving only the exponent.\n        uint256 exponent = uint8(Number.unwrap(number));\n        if (exponent == 0xFF) {\n            return mantissa;\n        } else {\n            unchecked {\n                return (256 + mantissa) \u003c\u003c (exponent);\n            }\n        }\n    }\n\n    /// @dev Returns the most significant bit of `x`\n    /// https://solidity-by-example.org/bitwise/\n    function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\n        // To find `msb` we determine it bit by bit, starting from the highest one.\n        // `0 \u003c= msb \u003c= 255`, so we start from the highest bit, 1\u003c\u003c7 == 128.\n        // If `x` is at least 2**128, then the highest bit of `x` is at least 128.\n        // solhint-disable no-inline-assembly\n        assembly {\n            // `f` is set to 1\u003c\u003c7 if `x \u003e= 2**128` and to 0 otherwise.\n            let f := shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\n            // If `x \u003e= 2**128` then set `msb` highest bit to 1 and shift `x` right by 128.\n            // Otherwise, `msb` remains 0 and `x` remains unchanged.\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        // `x` is now at most 2**128 - 1. Continue the same way, the next highest bit is 1\u003c\u003c6 == 64.\n        assembly {\n            // `f` is set to 1\u003c\u003c6 if `x \u003e= 2**64` and to 0 otherwise.\n            let f := shl(6, gt(x, 0xFFFFFFFFFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c5 if `x \u003e= 2**32` and to 0 otherwise.\n            let f := shl(5, gt(x, 0xFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c4 if `x \u003e= 2**16` and to 0 otherwise.\n            let f := shl(4, gt(x, 0xFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c3 if `x \u003e= 2**8` and to 0 otherwise.\n            let f := shl(3, gt(x, 0xFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c2 if `x \u003e= 2**4` and to 0 otherwise.\n            let f := shl(2, gt(x, 0xF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c1 if `x \u003e= 2**2` and to 0 otherwise.\n            let f := shl(1, gt(x, 0x3))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1 if `x \u003e= 2**1` and to 0 otherwise.\n            let f := gt(x, 0x1)\n            msb := or(msb, f)\n        }\n    }\n\n    /// @dev Wraps (mantissa, exponent) pair into Number.\n    function _encode(uint8 mantissa, uint8 exponent) private pure returns (Number) {\n        // Casts below are upcasts, so they are safe.\n        return Number.wrap(uint16(mantissa) \u003c\u003c SHIFT_MANTISSA | uint16(exponent));\n    }\n}\n\n// contracts/libs/stack/Request.sol\n\n/// Request is encoded data with \"message execution request\".\ntype Request is uint192;\n\nusing RequestLib for Request global;\n\n/// Library for formatting _the request part_ of _the base messages_.\n/// - Request represents a message sender requirements for the message execution on the destination chain.\n/// - Request occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n/// \u003e gasDrop field is included for future compatibility and is ignored at the moment.\n///\n/// # Request stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type   | Bytes | Description                                          |\n/// | ---------- | -------- | ------ | ----- | ---------------------------------------------------- |\n/// | (024..012] | gasDrop  | uint96 | 12    | Minimum amount of gas token to drop to the recipient |\n/// | (012..004] | gasLimit | uint64 | 8     | Minimum amount of gas units to supply for execution  |\n/// | (004..000] | version  | uint32 | 4     | Base message version to pass to the recipient        |\n\nlibrary RequestLib {\n    /// @dev Amount of bits to shift to gasDrop field\n    uint192 private constant SHIFT_GAS_DROP = 12 * 8;\n    /// @dev Amount of bits to shift to gasLimit field\n    uint192 private constant SHIFT_GAS_LIMIT = 4 * 8;\n\n    /// @notice Returns an encoded request with the given fields\n    /// @param gasDrop_     Minimum amount of gas token to drop to the recipient (ignored at the moment)\n    /// @param gasLimit_    Minimum amount of gas units to supply for execution\n    /// @param version_     Base message version to pass to the recipient\n    function encodeRequest(uint96 gasDrop_, uint64 gasLimit_, uint32 version_) internal pure returns (Request) {\n        // Casts below are upcasts, so they are safe\n        return Request.wrap(uint192(gasDrop_) \u003c\u003c SHIFT_GAS_DROP | uint192(gasLimit_) \u003c\u003c SHIFT_GAS_LIMIT | version_);\n    }\n\n    /// @notice Wraps the padded encoded request into a Request-typed value.\n    /// @dev The \"padded\" request is simply an encoded request casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded requests\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedRequest) internal pure returns (Request) {\n        // Casting to uint192 will truncate the highest bits, which is the behavior we want\n        return Request.wrap(uint192(paddedRequest));\n    }\n\n    /// @notice Returns the requested of gas token to drop to the recipient.\n    function gasDrop(Request request) internal pure returns (uint96) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return uint96(Request.unwrap(request) \u003e\u003e SHIFT_GAS_DROP);\n    }\n\n    /// @notice Returns the requested minimum amount of gas units to supply for execution.\n    function gasLimit(Request request) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Request.unwrap(request) \u003e\u003e SHIFT_GAS_LIMIT);\n    }\n\n    /// @notice Returns the requested base message version to pass to the recipient.\n    function version(Request request) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Request.unwrap(request));\n    }\n}\n\n// node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        require(value \u003c= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        require(value \u003c= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        require(value \u003c= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value \u003c= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        require(value \u003c= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        require(value \u003c= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        require(value \u003c= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        require(value \u003c= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        require(value \u003c= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        require(value \u003c= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        require(value \u003c= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        require(value \u003c= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        require(value \u003c= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        require(value \u003c= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        require(value \u003c= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value \u003c= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        require(value \u003c= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        require(value \u003c= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        require(value \u003c= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value \u003c= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        require(value \u003c= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        require(value \u003c= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        require(value \u003c= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value \u003c= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        require(value \u003c= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        require(value \u003c= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        require(value \u003c= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value \u003c= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        require(value \u003c= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value \u003c= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value \u003c= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     *\n     * _Available since v3.0._\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value \u003e= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     *\n     * _Available since v3.0._\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value \u003c= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     *\n     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length \u003e 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance \u003e= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance \u003e= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length \u003e 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n\n// contracts/base/MultiCallable.sol\n\n/// @notice Collection of Multicall utilities. Fork of Multicall3:\n/// https://github.com/mds1/multicall/blob/master/src/Multicall3.sol\nabstract contract MultiCallable {\n    struct Call {\n        bool allowFailure;\n        bytes callData;\n    }\n\n    struct Result {\n        bool success;\n        bytes returnData;\n    }\n\n    /// @notice Aggregates a few calls to this contract into one multicall without modifying `msg.sender`.\n    function multicall(Call[] calldata calls) external returns (Result[] memory callResults) {\n        uint256 amount = calls.length;\n        callResults = new Result[](amount);\n        Call calldata call_;\n        for (uint256 i = 0; i \u003c amount;) {\n            call_ = calls[i];\n            Result memory result = callResults[i];\n            // We perform a delegate call to ourselves here. Delegate call does not modify `msg.sender`, so\n            // this will have the same effect as if `msg.sender` performed all the calls themselves one by one.\n            // solhint-disable-next-line avoid-low-level-calls\n            (result.success, result.returnData) = address(this).delegatecall(call_.callData);\n            // solhint-disable-next-line no-inline-assembly\n            assembly {\n                // Revert if the call fails and failure is not allowed\n                // `allowFailure := calldataload(call_)` and `success := mload(result)`\n                if iszero(or(calldataload(call_), mload(result))) {\n                    // Revert with `0x4d6a2328` (function selector for `MulticallFailed()`)\n                    mstore(0x00, 0x4d6a232800000000000000000000000000000000000000000000000000000000)\n                    revert(0x00, 0x04)\n                }\n            }\n            unchecked {\n                ++i;\n            }\n        }\n    }\n}\n\n// contracts/base/Version.sol\n\n/**\n * @title Versioned\n * @notice Version getter for contracts. Doesn't use any storage slots, meaning\n * it will never cause any troubles with the upgradeable contracts. For instance, this contract\n * can be added or removed from the inheritance chain without shifting the storage layout.\n */\nabstract contract Versioned {\n    /**\n     * @notice Struct that is mimicking the storage layout of a string with 32 bytes or less.\n     * Length is limited by 32, so the whole string payload takes two memory words:\n     * @param length    String length\n     * @param data      String characters\n     */\n    struct _ShortString {\n        uint256 length;\n        bytes32 data;\n    }\n\n    /// @dev Length of the \"version string\"\n    uint256 private immutable _length;\n    /// @dev Bytes representation of the \"version string\".\n    /// Strings with length over 32 are not supported!\n    bytes32 private immutable _data;\n\n    constructor(string memory version_) {\n        _length = bytes(version_).length;\n        if (_length \u003e 32) revert IncorrectVersionLength();\n        // bytes32 is left-aligned =\u003e this will store the byte representation of the string\n        // with the trailing zeroes to complete the 32-byte word\n        _data = bytes32(bytes(version_));\n    }\n\n    function version() external view returns (string memory versionString) {\n        // Load the immutable values to form the version string\n        _ShortString memory str = _ShortString(_length, _data);\n        // The only way to do this cast is doing some dirty assembly\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            versionString := str\n        }\n    }\n}\n\n// contracts/libs/ChainContext.sol\n\n/// @notice Library for accessing chain context variables as tightly packed integers.\n/// Messaging contracts should rely on this library for accessing chain context variables\n/// instead of doing the casting themselves.\nlibrary ChainContext {\n    using SafeCast for uint256;\n\n    /// @notice Returns the current block number as uint40.\n    /// @dev Reverts if block number is greater than 40 bits, which is not supposed to happen\n    /// until the block.timestamp overflows (assuming block time is at least 1 second).\n    function blockNumber() internal view returns (uint40) {\n        return block.number.toUint40();\n    }\n\n    /// @notice Returns the current block timestamp as uint40.\n    /// @dev Reverts if block timestamp is greater than 40 bits, which is\n    /// supposed to happen approximately in year 36835.\n    function blockTimestamp() internal view returns (uint40) {\n        return block.timestamp.toUint40();\n    }\n\n    /// @notice Returns the chain id as uint32.\n    /// @dev Reverts if chain id is greater than 32 bits, which is not\n    /// supposed to happen in production.\n    function chainId() internal view returns (uint32) {\n        return block.chainid.toUint32();\n    }\n}\n\n// contracts/libs/Structures.sol\n\n// Here we define common enums and structures to enable their easier reusing later.\n\n// ═══════════════════════════════ AGENT STATUS ════════════════════════════════\n\n/// @dev Potential statuses for the off-chain bonded agent:\n/// - Unknown: never provided a bond =\u003e signature not valid\n/// - Active: has a bond in BondingManager =\u003e signature valid\n/// - Unstaking: has a bond in BondingManager, initiated the unstaking =\u003e signature not valid\n/// - Resting: used to have a bond in BondingManager, successfully unstaked =\u003e signature not valid\n/// - Fraudulent: proven to commit fraud, value in Merkle Tree not updated =\u003e signature not valid\n/// - Slashed: proven to commit fraud, value in Merkle Tree was updated =\u003e signature not valid\n/// Unstaked agent could later be added back to THE SAME domain by staking a bond again.\n/// Honest agent: Unknown -\u003e Active -\u003e unstaking -\u003e Resting -\u003e Active ...\n/// Malicious agent: Unknown -\u003e Active -\u003e Fraudulent -\u003e Slashed\n/// Malicious agent: Unknown -\u003e Active -\u003e Unstaking -\u003e Fraudulent -\u003e Slashed\nenum AgentFlag {\n    Unknown,\n    Active,\n    Unstaking,\n    Resting,\n    Fraudulent,\n    Slashed\n}\n\n/// @notice Struct for storing an agent in the BondingManager contract.\nstruct AgentStatus {\n    AgentFlag flag;\n    uint32 domain;\n    uint32 index;\n}\n// 184 bits available for tight packing\n\nusing StructureUtils for AgentStatus global;\n\n/// @notice Potential statuses of an agent in terms of being in dispute\n/// - None: agent is not in dispute\n/// - Pending: agent is in unresolved dispute\n/// - Slashed: agent was in dispute that lead to agent being slashed\n/// Note: agent who won the dispute has their status reset to None\nenum DisputeFlag {\n    None,\n    Pending,\n    Slashed\n}\n\n/// @notice Struct for storing dispute status of an agent.\n/// @param flag         Dispute flag: None/Pending/Slashed.\n/// @param openedAt     Timestamp when the latest agent dispute was opened (zero if not opened).\n/// @param resolvedAt   Timestamp when the latest agent dispute was resolved (zero if not resolved).\nstruct DisputeStatus {\n    DisputeFlag flag;\n    uint40 openedAt;\n    uint40 resolvedAt;\n}\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\n/// @notice Struct representing the status of Destination contract.\n/// @param snapRootTime     Timestamp when latest snapshot root was accepted\n/// @param agentRootTime    Timestamp when latest agent root was accepted\n/// @param notaryIndex      Index of Notary who signed the latest agent root\nstruct DestinationStatus {\n    uint40 snapRootTime;\n    uint40 agentRootTime;\n    uint32 notaryIndex;\n}\n\n// ═══════════════════════════════ EXECUTION HUB ═══════════════════════════════\n\n/// @notice Potential statuses of the message in Execution Hub.\n/// - None: there hasn't been a valid attempt to execute the message yet\n/// - Failed: there was a valid attempt to execute the message, but recipient reverted\n/// - Success: there was a valid attempt to execute the message, and recipient did not revert\n/// Note: message can be executed until its status is Success\nenum MessageStatus {\n    None,\n    Failed,\n    Success\n}\n\nlibrary StructureUtils {\n    /// @notice Checks that Agent is Active\n    function verifyActive(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active) {\n            revert AgentNotActive();\n        }\n    }\n\n    /// @notice Checks that Agent is Unstaking\n    function verifyUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Unstaking) {\n            revert AgentNotUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Active or Unstaking\n    function verifyActiveUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active \u0026\u0026 status.flag != AgentFlag.Unstaking) {\n            revert AgentNotActiveNorUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Fraudulent\n    function verifyFraudulent(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Fraudulent) {\n            revert AgentNotFraudulent();\n        }\n    }\n\n    /// @notice Checks that Agent is not Unknown\n    function verifyKnown(AgentStatus memory status) internal pure {\n        if (status.flag == AgentFlag.Unknown) {\n            revert AgentUnknown();\n        }\n    }\n}\n\n// contracts/libs/memory/MemView.sol\n\n/// @dev MemView is an untyped view over a portion of memory to be used instead of `bytes memory`\ntype MemView is uint256;\n\n/// @dev Attach library functions to MemView\nusing MemViewLib for MemView global;\n\n/// @notice Library for operations with the memory views.\n/// Forked from https://github.com/summa-tx/memview-sol with several breaking changes:\n/// - The codebase is ported to Solidity 0.8\n/// - Custom errors are added\n/// - The runtime type checking is replaced with compile-time check provided by User-Defined Value Types\n///   https://docs.soliditylang.org/en/latest/types.html#user-defined-value-types\n/// - uint256 is used as the underlying type for the \"memory view\" instead of bytes29.\n///   It is wrapped into MemView custom type in order not to be confused with actual integers.\n/// - Therefore the \"type\" field is discarded, allowing to allocate 16 bytes for both view location and length\n/// - The documentation is expanded\n/// - Library functions unused by the rest of the codebase are removed\n//  - Very pretty code separators are added :)\nlibrary MemViewLib {\n    /// @notice Stack layout for uint256 (from highest bits to lowest)\n    /// (32 .. 16]      loc     16 bytes    Memory address of underlying bytes\n    /// (16 .. 00]      len     16 bytes    Length of underlying bytes\n\n    // ═══════════════════════════════════════════ BUILDING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Instantiate a new untyped memory view. This should generally not be called directly.\n     * Prefer `ref` wherever possible.\n     * @param loc_          The memory address\n     * @param len_          The length\n     * @return The new view with the specified location and length\n     */\n    function build(uint256 loc_, uint256 len_) internal pure returns (MemView) {\n        uint256 end_ = loc_ + len_;\n        // Make sure that a view is not constructed that points to unallocated memory\n        // as this could be indicative of a buffer overflow attack\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            if gt(end_, mload(0x40)) { end_ := 0 }\n        }\n        if (end_ == 0) {\n            revert UnallocatedMemory();\n        }\n        return _unsafeBuildUnchecked(loc_, len_);\n    }\n\n    /**\n     * @notice Instantiate a memory view from a byte array.\n     * @dev Note that due to Solidity memory representation, it is not possible to\n     * implement a deref, as the `bytes` type stores its len in memory.\n     * @param arr           The byte array\n     * @return The memory view over the provided byte array\n     */\n    function ref(bytes memory arr) internal pure returns (MemView) {\n        uint256 len_ = arr.length;\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 loc_;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // We add 0x20, so that the view starts exactly where the array data starts\n            loc_ := add(arr, 0x20)\n        }\n        return build(loc_, len_);\n    }\n\n    // ════════════════════════════════════════════ CLONING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to the new memory.\n     * @param memView       The memory view\n     * @return arr          The cloned byte array\n     */\n    function clone(MemView memView) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        unchecked {\n            _unsafeCopyTo(memView, ptr + 0x20);\n        }\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 len_ = memView.len();\n        uint256 footprint_ = memView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    /**\n     * @notice Copies all views, joins them into a new bytearray.\n     * @param memViews      The memory views\n     * @return arr          The new byte array with joined data behind the given views\n     */\n    function join(MemView[] memory memViews) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        MemView newView;\n        unchecked {\n            newView = _unsafeJoin(memViews, ptr + 0x20);\n        }\n        uint256 len_ = newView.len();\n        uint256 footprint_ = newView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    // ══════════════════════════════════════════ INSPECTING MEMORY VIEW ═══════════════════════════════════════════════\n\n    /**\n     * @notice Returns the memory address of the underlying bytes.\n     * @param memView       The memory view\n     * @return loc_         The memory address\n     */\n    function loc(MemView memView) internal pure returns (uint256 loc_) {\n        // loc is stored in the highest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u003e\u003e 128;\n    }\n\n    /**\n     * @notice Returns the number of bytes of the view.\n     * @param memView       The memory view\n     * @return len_         The length of the view\n     */\n    function len(MemView memView) internal pure returns (uint256 len_) {\n        // len is stored in the lowest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u0026 type(uint128).max;\n    }\n\n    /**\n     * @notice Returns the endpoint of `memView`.\n     * @param memView       The memory view\n     * @return end_         The endpoint of `memView`\n     */\n    function end(MemView memView) internal pure returns (uint256 end_) {\n        // The endpoint never overflows uint128, let alone uint256, so we could use unchecked math here\n        unchecked {\n            return memView.loc() + memView.len();\n        }\n    }\n\n    /**\n     * @notice Returns the number of memory words this memory view occupies, rounded up.\n     * @param memView       The memory view\n     * @return words_       The number of memory words\n     */\n    function words(MemView memView) internal pure returns (uint256 words_) {\n        // returning ceil(length / 32.0)\n        unchecked {\n            return (memView.len() + 31) \u003e\u003e 5;\n        }\n    }\n\n    /**\n     * @notice Returns the in-memory footprint of a fresh copy of the view.\n     * @param memView       The memory view\n     * @return footprint_   The in-memory footprint of a fresh copy of the view.\n     */\n    function footprint(MemView memView) internal pure returns (uint256 footprint_) {\n        // words() * 32\n        return memView.words() \u003c\u003c 5;\n    }\n\n    // ════════════════════════════════════════════ HASHING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the keccak256 hash of the underlying memory\n     * @param memView       The memory view\n     * @return digest       The keccak256 hash of the underlying memory\n     */\n    function keccak(MemView memView) internal pure returns (bytes32 digest) {\n        uint256 loc_ = memView.loc();\n        uint256 len_ = memView.len();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            digest := keccak256(loc_, len_)\n        }\n    }\n\n    /**\n     * @notice Adds a salt to the keccak256 hash of the underlying data and returns the keccak256 hash of the\n     * resulting data.\n     * @param memView       The memory view\n     * @return digestSalted keccak256(salt, keccak256(memView))\n     */\n    function keccakSalted(MemView memView, bytes32 salt) internal pure returns (bytes32 digestSalted) {\n        return keccak256(bytes.concat(salt, memView.keccak()));\n    }\n\n    // ════════════════════════════════════════════ SLICING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Safe slicing without memory modification.\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the given index\n     */\n    function slice(MemView memView, uint256 index_, uint256 len_) internal pure returns (MemView) {\n        uint256 loc_ = memView.loc();\n        // Ensure it doesn't overrun the view\n        if (loc_ + index_ + len_ \u003e memView.end()) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // loc_ + index_ \u003c= memView.end()\n            return build({loc_: loc_ + index_, len_: len_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing bytes from `index` to end(memView).\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @return The new view for the slice starting from the given index until the initial view endpoint\n     */\n    function sliceFrom(MemView memView, uint256 index_) internal pure returns (MemView) {\n        uint256 len_ = memView.len();\n        // Ensure it doesn't overrun the view\n        if (index_ \u003e len_) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // index_ \u003c= len_ =\u003e memView.loc() + index_ \u003c= memView.loc() + memView.len() == memView.end()\n            return build({loc_: memView.loc() + index_, len_: len_ - index_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the first `len` bytes.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the initial view beginning\n     */\n    function prefix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        return memView.slice({index_: 0, len_: len_});\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the last `len` byte.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length until the initial view endpoint\n     */\n    function postfix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        uint256 viewLen = memView.len();\n        // Ensure it doesn't overrun the view\n        if (len_ \u003e viewLen) {\n            revert ViewOverrun();\n        }\n        // Could do the unchecked math due to the check above\n        uint256 index_;\n        unchecked {\n            index_ = viewLen - len_;\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // len_ \u003c= memView.len() =\u003e memView.loc() \u003c= loc_ \u003c= memView.end()\n            return build({loc_: memView.loc() + viewLen - len_, len_: len_});\n        }\n    }\n\n    // ═══════════════════════════════════════════ INDEXING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Load up to 32 bytes from the view onto the stack.\n     * @dev Returns a bytes32 with only the `bytes_` HIGHEST bytes set.\n     * This can be immediately cast to a smaller fixed-length byte array.\n     * To automatically cast to an integer, use `indexUint`.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return result       The 32 byte result having only `bytes_` highest bytes set\n     */\n    function index(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (bytes32 result) {\n        if (bytes_ == 0) {\n            return bytes32(0);\n        }\n        // Can't load more than 32 bytes to the stack in one go\n        if (bytes_ \u003e 32) {\n            revert IndexedTooMuch();\n        }\n        // The last indexed byte should be within view boundaries\n        if (index_ + bytes_ \u003e memView.len()) {\n            revert ViewOverrun();\n        }\n        uint256 bitLength = bytes_ \u003c\u003c 3; // bytes_ * 8\n        uint256 loc_ = memView.loc();\n        // Get a mask with `bitLength` highest bits set\n        uint256 mask;\n        // 0x800...00 binary representation is 100...00\n        // sar stands for \"signed arithmetic shift\": https://en.wikipedia.org/wiki/Arithmetic_shift\n        // sar(N-1, 100...00) = 11...100..00, with exactly N highest bits set to 1\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            mask := sar(sub(bitLength, 1), 0x8000000000000000000000000000000000000000000000000000000000000000)\n        }\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load a full word using index offset, and apply mask to ignore non-relevant bytes\n            result := and(mload(add(loc_, index_)), mask)\n        }\n    }\n\n    /**\n     * @notice Parse an unsigned integer from the view at `index`.\n     * @dev Requires that the view have \u003e= `bytes_` bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return The unsigned integer\n     */\n    function indexUint(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (uint256) {\n        bytes32 indexedBytes = memView.index(index_, bytes_);\n        // `index()` returns left-aligned `bytes_`, while integers are right-aligned\n        // Shifting here to right-align with the full 32 bytes word: need to shift right `(32 - bytes_)` bytes\n        unchecked {\n            // memView.index() reverts when bytes_ \u003e 32, thus unchecked math\n            return uint256(indexedBytes) \u003e\u003e ((32 - bytes_) \u003c\u003c 3);\n        }\n    }\n\n    /**\n     * @notice Parse an address from the view at `index`.\n     * @dev Requires that the view have \u003e= 20 bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @return The address\n     */\n    function indexAddress(MemView memView, uint256 index_) internal pure returns (address) {\n        // index 20 bytes as `uint160`, and then cast to `address`\n        return address(uint160(memView.indexUint(index_, 20)));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns a memory view over the specified memory location\n    /// without checking if it points to unallocated memory.\n    function _unsafeBuildUnchecked(uint256 loc_, uint256 len_) private pure returns (MemView) {\n        // There is no scenario where loc or len would overflow uint128, so we omit this check.\n        // We use the highest 128 bits to encode the location and the lowest 128 bits to encode the length.\n        return MemView.wrap((loc_ \u003c\u003c 128) | len_);\n    }\n\n    /**\n     * @notice Copy the view to a location, return an unsafe memory reference\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memView       The memory view\n     * @param newLoc        The new location to copy the underlying view data\n     * @return The memory view over the unsafe memory with the copied underlying data\n     */\n    function _unsafeCopyTo(MemView memView, uint256 newLoc) private view returns (MemView) {\n        uint256 len_ = memView.len();\n        uint256 oldLoc = memView.loc();\n\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (newLoc \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        bool res;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // use the identity precompile (0x04) to copy\n            res := staticcall(gas(), 0x04, oldLoc, len_, newLoc, len_)\n        }\n        if (!res) revert PrecompileOutOfGas();\n        return _unsafeBuildUnchecked({loc_: newLoc, len_: len_});\n    }\n\n    /**\n     * @notice Join the views in memory, return an unsafe reference to the memory.\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memViews      The memory views\n     * @return The conjoined view pointing to the new memory\n     */\n    function _unsafeJoin(MemView[] memory memViews, uint256 location) private view returns (MemView) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (location \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        // Copy the views to the specified location one by one, by tracking the amount of copied bytes so far\n        uint256 offset = 0;\n        for (uint256 i = 0; i \u003c memViews.length;) {\n            MemView memView = memViews[i];\n            // We can use the unchecked math here as location + sum(view.length) will never overflow uint256\n            unchecked {\n                _unsafeCopyTo(memView, location + offset);\n                offset += memView.len();\n                ++i;\n            }\n        }\n        return _unsafeBuildUnchecked({loc_: location, len_: offset});\n    }\n}\n\n// contracts/libs/merkle/MerkleMath.sol\n\nlibrary MerkleMath {\n    // ═════════════════════════════════════════ BASIC MERKLE CALCULATIONS ═════════════════════════════════════════════\n\n    /**\n     * @notice Calculates the merkle root for the given leaf and merkle proof.\n     * @dev Will revert if proof length exceeds the tree height.\n     * @param index     Index of `leaf` in tree\n     * @param leaf      Leaf of the merkle tree\n     * @param proof     Proof of inclusion of `leaf` in the tree\n     * @param height    Height of the merkle tree\n     * @return root_    Calculated Merkle Root\n     */\n    function proofRoot(uint256 index, bytes32 leaf, bytes32[] memory proof, uint256 height)\n        internal\n        pure\n        returns (bytes32 root_)\n    {\n        // Proof length could not exceed the tree height\n        uint256 proofLen = proof.length;\n        if (proofLen \u003e height) revert TreeHeightTooLow();\n        root_ = leaf;\n        /// @dev Apply unchecked to all ++h operations\n        unchecked {\n            // Go up the tree levels from the leaf following the proof\n            for (uint256 h = 0; h \u003c proofLen; ++h) {\n                // Get a sibling node on current level: this is proof[h]\n                root_ = getParent(root_, proof[h], index, h);\n            }\n            // Go up to the root: the remaining siblings are EMPTY\n            for (uint256 h = proofLen; h \u003c height; ++h) {\n                root_ = getParent(root_, bytes32(0), index, h);\n            }\n        }\n    }\n\n    /**\n     * @notice Calculates the parent of a node on the path from one of the leafs to root.\n     * @param node          Node on a path from tree leaf to root\n     * @param sibling       Sibling for a given node\n     * @param leafIndex     Index of the tree leaf\n     * @param nodeHeight    \"Level height\" for `node` (ZERO for leafs, ORIGIN_TREE_HEIGHT for root)\n     */\n    function getParent(bytes32 node, bytes32 sibling, uint256 leafIndex, uint256 nodeHeight)\n        internal\n        pure\n        returns (bytes32 parent)\n    {\n        // Index for `node` on its \"tree level\" is (leafIndex / 2**height)\n        // \"Left child\" has even index, \"right child\" has odd index\n        if ((leafIndex \u003e\u003e nodeHeight) \u0026 1 == 0) {\n            // Left child\n            return getParent(node, sibling);\n        } else {\n            // Right child\n            return getParent(sibling, node);\n        }\n    }\n\n    /// @notice Calculates the parent of tow nodes in the merkle tree.\n    /// @dev We use implementation with H(0,0) = 0\n    /// This makes EVERY empty node in the tree equal to ZERO,\n    /// saving us from storing H(0,0), H(H(0,0), H(0, 0)), and so on\n    /// @param leftChild    Left child of the calculated node\n    /// @param rightChild   Right child of the calculated node\n    /// @return parent      Value for the node having above mentioned children\n    function getParent(bytes32 leftChild, bytes32 rightChild) internal pure returns (bytes32 parent) {\n        if (leftChild == bytes32(0) \u0026\u0026 rightChild == bytes32(0)) {\n            return 0;\n        } else {\n            return keccak256(bytes.concat(leftChild, rightChild));\n        }\n    }\n\n    // ════════════════════════════════ ROOT/PROOF CALCULATION FOR A LIST OF LEAFS ═════════════════════════════════════\n\n    /**\n     * @notice Calculates merkle root for a list of given leafs.\n     * Merkle Tree is constructed by padding the list with ZERO values for leafs until list length is `2**height`.\n     * Merkle Root is calculated for the constructed tree, and then saved in `leafs[0]`.\n     * \u003e Note:\n     * \u003e - `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * \u003e - Caller is expected not to reuse `hashes` list after the call, and only use `leafs[0]` value,\n     * which is guaranteed to contain the calculated merkle root.\n     * \u003e - root is calculated using the `H(0,0) = 0` Merkle Tree implementation. See MerkleTree.sol for details.\n     * @dev Amount of leaves should be at most `2**height`\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param height    Height of the Merkle Tree to construct\n     */\n    function calculateRoot(bytes32[] memory hashes, uint256 height) internal pure {\n        uint256 levelLength = hashes.length;\n        // Amount of hashes could not exceed amount of leafs in tree with the given height\n        if (levelLength \u003e (1 \u003c\u003c height)) revert TreeHeightTooLow();\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\": the amount of iterations for the for loop above.\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n            }\n        }\n    }\n\n    /**\n     * @notice Generates a proof of inclusion of a leaf in the list. If the requested index is outside\n     * of the list range, generates a proof of inclusion for an empty leaf (proof of non-inclusion).\n     * The Merkle Tree is constructed by padding the list with ZERO values until list length is a power of two\n     * __AND__ index is in the extended list range. For example:\n     *  - `hashes.length == 6` and `0 \u003c= index \u003c= 7` will \"extend\" the list to 8 entries.\n     *  - `hashes.length == 6` and `7 \u003c index \u003c= 15` will \"extend\" the list to 16 entries.\n     * \u003e Note: `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * Caller is expected not to reuse `hashes` list after the call.\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param index     Leaf index to generate the proof for\n     * @return proof    Generated merkle proof\n     */\n    function calculateProof(bytes32[] memory hashes, uint256 index) internal pure returns (bytes32[] memory proof) {\n        // Use only meaningful values for the shortened proof\n        // Check if index is within the list range (we want to generates proofs for outside leafs as well)\n        uint256 height = getHeight(index \u003c hashes.length ? hashes.length : (index + 1));\n        proof = new bytes32[](height);\n        uint256 levelLength = hashes.length;\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Use sibling for the merkle proof; `index^1` is index of our sibling\n                proof[h] = (index ^ 1 \u003c levelLength) ? hashes[index ^ 1] : bytes32(0);\n\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\"\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n                // Traverse to parent node\n                index \u003e\u003e= 1;\n            }\n        }\n    }\n\n    /// @notice Returns the height of the tree having a given amount of leafs.\n    function getHeight(uint256 leafs) internal pure returns (uint256 height) {\n        uint256 amount = 1;\n        while (amount \u003c leafs) {\n            unchecked {\n                ++height;\n            }\n            amount \u003c\u003c= 1;\n        }\n    }\n}\n\n// contracts/libs/stack/GasData.sol\n\n/// GasData in encoded data with \"basic information about gas prices\" for some chain.\ntype GasData is uint96;\n\nusing GasDataLib for GasData global;\n\n/// ChainGas is encoded data with given chain's \"basic information about gas prices\".\ntype ChainGas is uint128;\n\nusing GasDataLib for ChainGas global;\n\n/// Library for encoding and decoding GasData and ChainGas structs.\n/// # GasData\n/// `GasData` is a struct to store the \"basic information about gas prices\", that could\n/// be later used to approximate the cost of a message execution, and thus derive the\n/// minimal tip values for sending a message to the chain.\n/// \u003e - `GasData` is supposed to be cached by `GasOracle` contract, allowing to store the\n/// \u003e approximates instead of the exact values, and thus save on storage costs.\n/// \u003e - For instance, if `GasOracle` only updates the values on +- 10% change, having an\n/// \u003e 0.4% error on the approximates would be acceptable.\n/// `GasData` is supposed to be included in the Origin's state, which are synced across\n/// chains using Agent-signed snapshots and attestations.\n/// ## GasData stack layout (from highest bits to lowest)\n///\n/// | Position   | Field        | Type   | Bytes | Description                                         |\n/// | ---------- | ------------ | ------ | ----- | --------------------------------------------------- |\n/// | (012..010] | gasPrice     | uint16 | 2     | Gas price for the chain (in Wei per gas unit)       |\n/// | (010..008] | dataPrice    | uint16 | 2     | Calldata price (in Wei per byte of content)         |\n/// | (008..006] | execBuffer   | uint16 | 2     | Tx fee safety buffer for message execution (in Wei) |\n/// | (006..004] | amortAttCost | uint16 | 2     | Amortized cost for attestation submission (in Wei)  |\n/// | (004..002] | etherPrice   | uint16 | 2     | Chain's Ether Price / Mainnet Ether Price (in BWAD) |\n/// | (002..000] | markup       | uint16 | 2     | Markup for the message execution (in BWAD)          |\n/// \u003e See Number.sol for more details on `Number` type and BWAD (binary WAD) math.\n///\n/// ## ChainGas stack layout (from highest bits to lowest)\n///\n/// | Position   | Field   | Type   | Bytes | Description      |\n/// | ---------- | ------- | ------ | ----- | ---------------- |\n/// | (016..004] | gasData | uint96 | 12    | Chain's gas data |\n/// | (004..000] | domain  | uint32 | 4     | Chain's domain   |\nlibrary GasDataLib {\n    /// @dev Amount of bits to shift to gasPrice field\n    uint96 private constant SHIFT_GAS_PRICE = 10 * 8;\n    /// @dev Amount of bits to shift to dataPrice field\n    uint96 private constant SHIFT_DATA_PRICE = 8 * 8;\n    /// @dev Amount of bits to shift to execBuffer field\n    uint96 private constant SHIFT_EXEC_BUFFER = 6 * 8;\n    /// @dev Amount of bits to shift to amortAttCost field\n    uint96 private constant SHIFT_AMORT_ATT_COST = 4 * 8;\n    /// @dev Amount of bits to shift to etherPrice field\n    uint96 private constant SHIFT_ETHER_PRICE = 2 * 8;\n\n    /// @dev Amount of bits to shift to gasData field\n    uint128 private constant SHIFT_GAS_DATA = 4 * 8;\n\n    // ═════════════════════════════════════════════════ GAS DATA ══════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded GasData struct with the given fields.\n    /// @param gasPrice_        Gas price for the chain (in Wei per gas unit)\n    /// @param dataPrice_       Calldata price (in Wei per byte of content)\n    /// @param execBuffer_      Tx fee safety buffer for message execution (in Wei)\n    /// @param amortAttCost_    Amortized cost for attestation submission (in Wei)\n    /// @param etherPrice_      Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n    /// @param markup_          Markup for the message execution (in BWAD)\n    function encodeGasData(\n        Number gasPrice_,\n        Number dataPrice_,\n        Number execBuffer_,\n        Number amortAttCost_,\n        Number etherPrice_,\n        Number markup_\n    ) internal pure returns (GasData) {\n        // Number type wraps uint16, so could safely be casted to uint96\n        // forgefmt: disable-next-item\n        return GasData.wrap(\n            uint96(Number.unwrap(gasPrice_)) \u003c\u003c SHIFT_GAS_PRICE |\n            uint96(Number.unwrap(dataPrice_)) \u003c\u003c SHIFT_DATA_PRICE |\n            uint96(Number.unwrap(execBuffer_)) \u003c\u003c SHIFT_EXEC_BUFFER |\n            uint96(Number.unwrap(amortAttCost_)) \u003c\u003c SHIFT_AMORT_ATT_COST |\n            uint96(Number.unwrap(etherPrice_)) \u003c\u003c SHIFT_ETHER_PRICE |\n            uint96(Number.unwrap(markup_))\n        );\n    }\n\n    /// @notice Wraps padded uint256 value into GasData struct.\n    function wrapGasData(uint256 paddedGasData) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(paddedGasData));\n    }\n\n    /// @notice Returns the gas price, in Wei per gas unit.\n    function gasPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_GAS_PRICE));\n    }\n\n    /// @notice Returns the calldata price, in Wei per byte of content.\n    function dataPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_DATA_PRICE));\n    }\n\n    /// @notice Returns the tx fee safety buffer for message execution, in Wei.\n    function execBuffer(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_EXEC_BUFFER));\n    }\n\n    /// @notice Returns the amortized cost for attestation submission, in Wei.\n    function amortAttCost(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_AMORT_ATT_COST));\n    }\n\n    /// @notice Returns the ratio of Chain's Ether Price / Mainnet Ether Price, in BWAD math.\n    function etherPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_ETHER_PRICE));\n    }\n\n    /// @notice Returns the markup for the message execution, in BWAD math.\n    function markup(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data)));\n    }\n\n    // ════════════════════════════════════════════════ CHAIN DATA ═════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded ChainGas struct with the given fields.\n    /// @param gasData_ Chain's gas data\n    /// @param domain_  Chain's domain\n    function encodeChainGas(GasData gasData_, uint32 domain_) internal pure returns (ChainGas) {\n        // GasData type wraps uint96, so could safely be casted to uint128\n        return ChainGas.wrap(uint128(GasData.unwrap(gasData_)) \u003c\u003c SHIFT_GAS_DATA | uint128(domain_));\n    }\n\n    /// @notice Wraps padded uint256 value into ChainGas struct.\n    function wrapChainGas(uint256 paddedChainGas) internal pure returns (ChainGas) {\n        // Casting to uint128 will truncate the highest bits, which is the behavior we want\n        return ChainGas.wrap(uint128(paddedChainGas));\n    }\n\n    /// @notice Returns the chain's gas data.\n    function gasData(ChainGas data) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(ChainGas.unwrap(data) \u003e\u003e SHIFT_GAS_DATA));\n    }\n\n    /// @notice Returns the chain's domain.\n    function domain(ChainGas data) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(ChainGas.unwrap(data));\n    }\n\n    /// @notice Returns the hash for the list of ChainGas structs.\n    function snapGasHash(ChainGas[] memory snapGas) internal pure returns (bytes32 snapGasHash_) {\n        // Use assembly to calculate the hash of the array without copying it\n        // ChainGas takes a single word of storage, thus ChainGas[] is stored in the following way:\n        // 0x00: length of the array, in words\n        // 0x20: first ChainGas struct\n        // 0x40: second ChainGas struct\n        // And so on...\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Find the location where the array data starts, we add 0x20 to skip the length field\n            let loc := add(snapGas, 0x20)\n            // Load the length of the array (in words).\n            // Shifting left 5 bits is equivalent to multiplying by 32: this converts from words to bytes.\n            let len := shl(5, mload(snapGas))\n            // Calculate the hash of the array\n            snapGasHash_ := keccak256(loc, len)\n        }\n    }\n}\n\n// contracts/libs/stack/Header.sol\n\n/// Header is encoded data with \"general routing information\".\ntype Header is uint136;\n\nusing HeaderLib for Header global;\n\n/// Types of messages supported by Origin-Destination\n/// - Base: message sent by protocol user, contains tips\n/// - Manager: message sent between AgentManager contracts located on different chains, no tips\nenum MessageFlag {\n    Base,\n    Manager\n}\n\nusing HeaderLib for MessageFlag global;\n\n/// Library for formatting _the header part_ of _the messages used by Origin and Destination_.\n/// - Header represents general information for routing a Message for Origin and Destination.\n/// - Header occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n///\n/// # Header stack layout (from highest bits to lowest)\n///\n/// | Position   | Field            | Type   | Bytes | Description                             |\n/// | ---------- | ---------------- | ------ | ----- | --------------------------------------- |\n/// | (017..016] | flag             | uint8  | 1     | Flag specifying the type of message     |\n/// | (016..012] | origin           | uint32 | 4     | Domain where message originated         |\n/// | (012..008] | nonce            | uint32 | 4     | Message nonce on the origin domain      |\n/// | (008..004] | destination      | uint32 | 4     | Domain where message will be executed   |\n/// | (004..000] | optimisticPeriod | uint32 | 4     | Optimistic period that will be enforced |\nlibrary HeaderLib {\n    /// @dev Amount of bits to shift to flag field\n    uint136 private constant SHIFT_FLAG = 16 * 8;\n    /// @dev Amount of bits to shift to origin field\n    uint136 private constant SHIFT_ORIGIN = 12 * 8;\n    /// @dev Amount of bits to shift to nonce field\n    uint136 private constant SHIFT_NONCE = 8 * 8;\n    /// @dev Amount of bits to shift to destination field\n    uint136 private constant SHIFT_DESTINATION = 4 * 8;\n\n    /// @notice Returns an encoded header with provided fields\n    /// @param origin_              Domain of origin chain\n    /// @param nonce_               Message nonce on origin chain\n    /// @param destination_         Domain of destination chain\n    /// @param optimisticPeriod_    Optimistic period for message execution\n    function encodeHeader(\n        MessageFlag flag_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint32 destination_,\n        uint32 optimisticPeriod_\n    ) internal pure returns (Header) {\n        // All casts below are upcasts, so they are safe\n        // forgefmt: disable-next-item\n        return Header.wrap(\n            uint136(uint8(flag_)) \u003c\u003c SHIFT_FLAG |\n            uint136(origin_) \u003c\u003c SHIFT_ORIGIN |\n            uint136(nonce_) \u003c\u003c SHIFT_NONCE |\n            uint136(destination_) \u003c\u003c SHIFT_DESTINATION |\n            uint136(optimisticPeriod_)\n        );\n    }\n\n    /// @notice Checks that the header is a valid encoded header.\n    function isHeader(uint256 paddedHeader) internal pure returns (bool) {\n        // Check that flag is within range\n        return _flag(paddedHeader) \u003c= uint8(type(MessageFlag).max);\n    }\n\n    /// @notice Wraps the padded encoded request into a Header-typed value.\n    /// @dev The \"padded\" header is simply an encoded header casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded headers\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedHeader) internal pure returns (Header) {\n        // Check that flag is within range\n        if (!isHeader(paddedHeader)) revert FlagOutOfRange();\n        // Casting to uint136 will truncate the highest bits, which is the behavior we want\n        return Header.wrap(uint136(paddedHeader));\n    }\n\n    /// @notice Returns header's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Header header) internal pure returns (bytes32 hashedHeader) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store header in scratch space\n            mstore(0, header)\n            // Compute hash of header padded to 32 bytes\n            hashedHeader := keccak256(0, 32)\n        }\n    }\n\n    // ══════════════════════════════════════════════ HEADER SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns header's flag field\n    function flag(Header header) internal pure returns (MessageFlag) {\n        // We check that flag is within range when wrapping the header, so this cast is safe\n        return MessageFlag(_flag(Header.unwrap(header)));\n    }\n\n    /// @notice Returns header's origin field\n    function origin(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_ORIGIN);\n    }\n\n    /// @notice Returns header's nonce field\n    function nonce(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_NONCE);\n    }\n\n    /// @notice Returns header's destination field\n    function destination(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_DESTINATION);\n    }\n\n    /// @notice Returns header's optimistic seconds field\n    function optimisticPeriod(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns header's flag field without casting to MessageFlag\n    function _flag(uint256 paddedHeader) private pure returns (uint8) {\n        // Casting to uint8 will truncate the highest bits, which is the behavior we want\n        return uint8(paddedHeader \u003e\u003e SHIFT_FLAG);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n     * constructor.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall \u0026\u0026 _initialized \u003c 1) || (!AddressUpgradeable.isContract(address(this)) \u0026\u0026 _initialized == 1),\n            \"Initializable: contract is already initialized\"\n        );\n        _initialized = 1;\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: setting the version to 255 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing \u0026\u0026 _initialized \u003c version, \"Initializable: contract is already initialized\");\n        _initialized = version;\n        _initializing = true;\n        _;\n        _initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        require(_initializing, \"Initializable: contract is not initializing\");\n        _;\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized != type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint8) {\n        return _initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _initializing;\n    }\n}\n\n// contracts/interfaces/IAgentManager.sol\n\ninterface IAgentManager {\n    /**\n     * @notice Allows Inbox to open a Dispute between a Guard and a Notary, if they are both not in Dispute already.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Guard or Notary is already in Dispute.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Allows Inbox to slash an agent, if their fraud was proven.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Domain doesn't match the saved agent domain.\n     * @param domain    Domain where the Agent is active\n     * @param agent     Address of the Agent\n     * @param prover    Address that initially provided fraud proof\n     */\n    function slashAgent(uint32 domain, address agent, address prover) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest known root of the Agent Merkle Tree.\n     */\n    function agentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns the number of opened Disputes.\n     * @dev This includes the Disputes that have been resolved already.\n     */\n    function getDisputesAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns information about the dispute with the given index.\n     * @dev Will revert if dispute with given index hasn't been opened yet.\n     * @param index             Dispute index\n     * @return guard            Address of the Guard in the Dispute\n     * @return notary           Address of the Notary in the Dispute\n     * @return slashedAgent     Address of the Agent who was slashed when Dispute was resolved\n     * @return fraudProver      Address who provided fraud proof to resolve the Dispute\n     * @return reportPayload    Raw payload with report data that led to the Dispute\n     * @return reportSignature  Guard signature for the report payload\n     */\n    function getDispute(uint256 index)\n        external\n        view\n        returns (\n            address guard,\n            address notary,\n            address slashedAgent,\n            address fraudProver,\n            bytes memory reportPayload,\n            bytes memory reportSignature\n        );\n\n    /**\n     * @notice Returns the current Dispute status of a given agent. See Structures.sol for details.\n     * @dev Every returned value will be set to zero if agent was not slashed and is not in Dispute.\n     * `rival` and `disputePtr` will be set to zero if the agent was slashed without being in Dispute.\n     * @param agent         Agent address\n     * @return flag         Flag describing the current Dispute status for the agent: None/Pending/Slashed\n     * @return rival        Address of the rival agent in the Dispute\n     * @return fraudProver  Address who provided fraud proof to resolve the Dispute\n     * @return disputePtr   Index of the opened Dispute PLUS ONE. Zero if agent is not in Dispute.\n     */\n    function disputeStatus(address agent)\n        external\n        view\n        returns (DisputeFlag flag, address rival, address fraudProver, uint256 disputePtr);\n}\n\n// contracts/interfaces/IAgentSecured.sol\n\ninterface IAgentSecured {\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * between a Guard and a Notary has been opened.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * has been resolved due to one of the agents being slashed.\n     * \u003e `rivalIndex` will be ZERO, if the slashed agent was not in the Dispute.\n     * @param slashedIndex  Index of the slashed agent in the Agent Merkle Tree\n     * @param rivalIndex    Index of the their Dispute Rival in the Agent Merkle Tree\n     */\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the address of the local AgentManager contract, which is treated as\n     * the \"source of truth\" for agent statuses.\n     */\n    function agentManager() external view returns (address);\n\n    /**\n     * @notice Returns the address of the local Inbox contract, which is treated as\n     * the \"source of truth\" for agent-signed statements.\n     * @dev Inbox passes verified agent statements to `IAgentSecured` contract.\n     */\n    function inbox() external view returns (address);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns (flag, openedAt, resolvedAt) that describes the latest status of\n     * the latest dispute for an agent with a given index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param agentIndex    Agent index in the Agent Merkle Tree\n     * @return              Latest dispute status for the given agent: (flag, openedAt, resolvedAt)\n     */\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory);\n}\n\n// contracts/libs/memory/ByteString.sol\n\n/// @dev CallData is a memory view over the payload to be used for an external call, i.e.\n/// recipient.call(callData). Its length is always (4 + 32 * N) bytes:\n/// - First 4 bytes represent the function selector.\n/// - 32 * N bytes represent N words that function arguments occupy.\ntype CallData is uint256;\n\n/// @dev Attach library functions to CallData\nusing ByteString for CallData global;\n\n/// @dev Signature is a memory view over a \"65 bytes\" array representing a ECDSA signature.\ntype Signature is uint256;\n\n/// @dev Attach library functions to Signature\nusing ByteString for Signature global;\n\nlibrary ByteString {\n    using MemViewLib for bytes;\n\n    /**\n     * @dev non-compact ECDSA signatures are enforced as of OZ 4.7.3\n     *\n     *      Signature payload memory layout\n     * [000 .. 032) r   bytes32 32 bytes\n     * [032 .. 064) s   bytes32 32 bytes\n     * [064 .. 065) v   uint8    1 byte\n     */\n    uint256 internal constant SIGNATURE_LENGTH = 65;\n    uint256 private constant OFFSET_R = 0;\n    uint256 private constant OFFSET_S = 32;\n    uint256 private constant OFFSET_V = 64;\n\n    /**\n     * @dev Calldata memory layout\n     * [000 .. 004) selector    bytes4  4 bytes\n     *      Optional: N function arguments\n     * [004 .. 036) arg1        bytes32 32 bytes\n     *      ..\n     * [AAA .. END) argN        bytes32 32 bytes\n     */\n    uint256 internal constant SELECTOR_LENGTH = 4;\n    uint256 private constant OFFSET_SELECTOR = 0;\n    uint256 private constant OFFSET_ARGUMENTS = SELECTOR_LENGTH;\n\n    // ═════════════════════════════════════════════════ SIGNATURE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the signature payload from the given values.\n     * @dev Using ByteString.formatSignature({r: r, s: s, v: v}) will make sure\n     * that params are given in the right order.\n     */\n    function formatSignature(bytes32 r, bytes32 s, uint8 v) internal pure returns (bytes memory) {\n        return abi.encodePacked(r, s, v);\n    }\n\n    /**\n     * @notice Returns a Signature view over for the given payload.\n     * @dev Will revert if the payload is not a signature.\n     */\n    function castToSignature(bytes memory payload) internal pure returns (Signature) {\n        return castToSignature(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Signature view.\n     * @dev Will revert if the memory view is not over a signature.\n     */\n    function castToSignature(MemView memView) internal pure returns (Signature) {\n        if (!isSignature(memView)) revert UnformattedSignature();\n        return Signature.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a signature\n     */\n    function isSignature(MemView memView) internal pure returns (bool) {\n        return memView.len() == SIGNATURE_LENGTH;\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Signature signature) internal pure returns (MemView) {\n        return MemView.wrap(Signature.unwrap(signature));\n    }\n\n    // ═════════════════════════════════════════════ SIGNATURE SLICING ═════════════════════════════════════════════════\n\n    /// @notice Unpacks signature payload into (r, s, v) parameters.\n    /// @dev Make sure to verify signature length with isSignature() beforehand.\n    function toRSV(Signature signature) internal pure returns (bytes32 r, bytes32 s, uint8 v) {\n        // Get the underlying memory view\n        MemView memView = unwrap(signature);\n        r = memView.index({index_: OFFSET_R, bytes_: 32});\n        s = memView.index({index_: OFFSET_S, bytes_: 32});\n        // Can be safely casted to uint8, since we index a single byte\n        v = uint8(memView.indexUint({index_: OFFSET_V, bytes_: 1}));\n    }\n\n    // ═════════════════════════════════════════════════ CALLDATA ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the calldata with the modified arguments:\n     * the existing arguments are prepended with the arguments from the prefix.\n     * @dev Given:\n     *  - `calldata = abi.encodeWithSelector(foo.selector, d, e);`\n     *  - `prefix = abi.encode(a, b, c);`\n     *  - `a`, `b`, `c` are arguments of static type (i.e. not dynamically sized ones)\n     *      Then:\n     *  - Function will return abi.encodeWithSelector(foo.selector, a, c, c, d, e)\n     *  - Returned calldata will trigger `foo(a, b, c, d, e)` when used for a contract call.\n     * Note: for clarification as to what types are considered static, see\n     * https://docs.soliditylang.org/en/latest/abi-spec.html#formal-specification-of-the-encoding\n     * @param callData  Calldata that needs to be modified\n     * @param prefix    ABI-encoded arguments to use as the first arguments in the new calldata\n     * @return Modified calldata having prefix as the first arguments.\n     */\n    function addPrefix(CallData callData, bytes memory prefix) internal view returns (bytes memory) {\n        // Prefix should occupy a whole amount of words in memory\n        if (!_fullWords(prefix.length)) revert UnformattedCallDataPrefix();\n        MemView[] memory views = new MemView[](3);\n        // Use payload's function selector\n        views[0] = abi.encodePacked(callData.callSelector()).ref();\n        // Use prefix as the first arguments\n        views[1] = prefix.ref();\n        // Use payload's remaining arguments\n        views[2] = callData.arguments();\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a CallData view over for the given payload.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(bytes memory payload) internal pure returns (CallData) {\n        return castToCallData(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a CallData view.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(MemView memView) internal pure returns (CallData) {\n        if (!isCallData(memView)) revert UnformattedCallData();\n        return CallData.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a valid calldata, i.e.\n     * a function selector, followed by arbitrary amount of arguments.\n     */\n    function isCallData(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Calldata should at least have a function selector\n        if (length \u003c SELECTOR_LENGTH) return false;\n        // The remainder of the calldata should be exactly N memory words (N \u003e= 0)\n        return _fullWords(length - SELECTOR_LENGTH);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(CallData callData) internal pure returns (MemView) {\n        return MemView.wrap(CallData.unwrap(callData));\n    }\n\n    /// @notice Returns callData's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(CallData callData) internal pure returns (bytes32) {\n        return callData.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ CALLDATA SLICING ══════════════════════════════════════════════════\n\n    /**\n     * @notice Returns amount of memory words (32 byte chunks) the function arguments\n     * occupy in the calldata.\n     * @dev This might differ from amount of arguments supplied, if any of the arguments\n     * occupies more than one memory slot. It is true, however, that argument part of the payload\n     * occupies exactly N words, even for dynamic types like `bytes`\n     */\n    function argumentWords(CallData callData) internal pure returns (uint256) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        // Equivalent of (length - SELECTOR_LENGTH) / 32\n        return (memView.len() - SELECTOR_LENGTH) \u003e\u003e 5;\n    }\n\n    /// @notice Returns selector for the provided calldata.\n    function callSelector(CallData callData) internal pure returns (bytes4) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return bytes4(memView.index({index_: OFFSET_SELECTOR, bytes_: SELECTOR_LENGTH}));\n    }\n\n    /// @notice Returns abi encoded arguments for the provided calldata.\n    function arguments(CallData callData) internal pure returns (MemView) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return memView.sliceFrom({index_: OFFSET_ARGUMENTS});\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if length is full amount of memory words (32 bytes).\n    function _fullWords(uint256 length) internal pure returns (bool) {\n        // The equivalent of length % 32 == 0\n        return length \u0026 31 == 0;\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n    function __Context_init() internal onlyInitializing {\n    }\n\n    function __Context_init_unchained() internal onlyInitializing {\n    }\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[50] private __gap;\n}\n\n// contracts/libs/merkle/MerkleTree.sol\n\n/// `BaseTree` is a struct representing incremental merkle tree.\n/// - Contains only the current branch.\n/// - The number of inserted leaves is stored externally, and is later supplied for tree operations.\n/// - Has a fixed height of `ORIGIN_TREE_HEIGHT`.\n/// - Can store up to `2 ** ORIGIN_TREE_HEIGHT - 1` leaves.\n/// \u003e Note: the hash function for the tree `H(x, y)` is defined as:\n/// \u003e - `H(0,0) = 0`\n/// \u003e - `H(x,y) = keccak256(x, y), when (x != 0 || y != 0)`\n/// ## Invariant for leafs\n/// - The leftmost empty leaf has `index == count`, where `count` is the amount of the inserted leafs so far.\n/// - Value for any empty leaf or node is bytes32(0).\n/// ## Invariant for current branch\n/// `branch[i]` is always the value of a node on the i-th level.\n/// Levels are numbered from leafs to root: `0 .. ORIGIN_TREE_HEIGHT`.\n/// `branch[i]` stores the value for the node, such that:\n//  - The node is a \"left child\" (e.g. has an even index).\n/// - The node must have two non-empty children.\n/// - Out of all level's \"left child\" nodes with \"non-empty children\",\n/// the one with the biggest index (the rightmost one) is stored as `branch[i]`.\n/// \u003e __`branch` could be used to form a proof of inclusion for the first empty leaf (`index == count`).__\n/// _Here is how:_\n/// - Let's walk along the path from the \"first empty leaf\" to the root.\n/// - i-th bit of the \"first empty leaf\" index (which is equal to `count`) determines if the path's node\n/// for this i-th level is a \"left child\" or a \"right child\".\n/// - i-th bit in `count` is 0 → we are the left child on this level → sibling is the right child\n/// that does not exist yet → `proof[i] = bytes32(0)`.\n/// - i-th bit in `count` is 1 → we are the right child on this level → sibling is the left child\n/// sibling is the rightmost \"left child\" node on the level → `proof[i] = branch[i]`.\n/// \u003e Therefore `proof[i] = (count \u0026 (1 \u003c\u003c i)) == 0 ? bytes32(0) : branch[i])`\nstruct BaseTree {\n    bytes32[ORIGIN_TREE_HEIGHT] branch;\n}\n\nusing MerkleTree for BaseTree global;\n\n/// `HistoricalTree` is an incremental merkle tree keeping track of its historical merkle roots.\n/// \u003e - `roots[N]` is the root of the tree after `N` leafs were inserted\n/// \u003e - `roots[0] == bytes32(0)`\n/// @param tree     Incremental merkle tree\n/// @param roots    Historical merkle roots of the tree\nstruct HistoricalTree {\n    BaseTree tree;\n    bytes32[] roots;\n}\n\nusing MerkleTree for HistoricalTree global;\n\n/// `DynamicTree` is a struct representing a Merkle Tree with `2**AGENT_TREE_HEIGHT` leaves.\n/// - A single operation is available: update value for leaf with an arbitrary index (which might be a non-empty leaf).\n/// - This is done by requesting the proof of inclusion for the old value, which is used to both\n/// verify the old value, and calculate the new root.\n/// \u003e Based on Original idea from [ER forum post](https://ethresear.ch/t/efficient-on-chain-dynamic-merkle-tree/11054).\nstruct DynamicTree {\n    bytes32 root;\n}\n\nusing MerkleTree for DynamicTree global;\n\n/// MerkleTree is work based on Nomad's Merkle.sol, which is used under MIT OR Apache-2.0\n/// [link](https://github.com/nomad-xyz/monorepo/blob/main/packages/contracts-core/contracts/libs/Merkle.sol).\n/// With the following changes:\n/// - Adapted for Solidity 0.8.x.\n/// - Amount of tree leaves stored externally.\n/// - Added thorough documentation.\n/// - `H(0,0) = 0` optimization from [ER forum post](https://ethresear.ch/t/optimizing-sparse-merkle-trees/3751/6).\n/// \u003e Nomad's Merkle.sol is work based on eth2 deposit contract, which is used under CC0-1.0\n///[link](https://github.com/ethereum/deposit_contract/blob/dev/deposit_contract/contracts/validator_registration.v.py).\n/// With the following changes:\n/// \u003e - Implemented in Solidity 0.7.6 (eth2 deposit contract implemented in Vyper).\n/// \u003e - `H() = keccak256()` is used as the hashing function instead of `sha256()`.\nlibrary MerkleTree {\n    /// @dev For root calculation we need at least one empty leaf, thus the minus one in the formula.\n    uint256 internal constant MAX_LEAVES = 2 ** ORIGIN_TREE_HEIGHT - 1;\n\n    // ═════════════════════════════════════════════════ BASE TREE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Inserts `node` into merkle tree\n     * @dev Reverts if tree is full\n     * @param newCount  Amount of inserted leaves in the tree after the insertion (i.e. current + 1)\n     * @param node      Element to insert into tree\n     */\n    function insertBase(BaseTree storage tree, uint256 newCount, bytes32 node) internal {\n        if (newCount \u003e MAX_LEAVES) revert MerkleTreeFull();\n        // We go up the tree following the branch from the empty leaf AFTER the just inserted one.\n        // We stop when we find the first \"right child\" node.\n        // Its sibling is now the rightmost \"left child\" node that has two non-empty children.\n        // Therefore we need to update `tree.branch` value on this level.\n        // One could see that `tree.branch` value on lower and higher levels remain unchanged.\n\n        // Loop invariant: `node` is the current level's value for the branch from JUST INSERTED leaf\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            if ((newCount \u0026 1) == 1) {\n                // Found the first \"right child\" node on the branch from EMPTY leaf\n                // `node` is the value for node on branch from JUST INSERTED leaf\n                // Which in this case is the \"left child\".\n                // We update tree.branch and exit\n                tree.branch[i] = node;\n                return;\n            }\n            // On the branch from EMPTY leaf this is still a \"left child\".\n            // Meaning on branch from JUST INSERTED leaf, `node` is a right child.\n            // We compute value for `node` parent using `tree.branch` invariant:\n            // This is the rightmost \"left child\" node, which would be sibling of `node`.\n            node = MerkleMath.getParent(tree.branch[i], node);\n            // Get the parent index, and go to the next tree level\n            newCount \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n        // As the loop should always end prematurely with the `return` statement,\n        // this code should be unreachable. We assert `false` just to be safe.\n        assert(false);\n    }\n\n    /**\n     * @notice Calculates and returns current root of the merkle tree.\n     * @param count     Current amount of inserted leaves in the tree\n     * @return current  Calculated root of `tree`\n     */\n    function rootBase(BaseTree storage tree, uint256 count) internal view returns (bytes32 current) {\n        // To calculate the root we follow the branch of first EMPTY leaf (index == count)\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            // Check if we are the left or the right child on the current level\n            if ((count \u0026 1) == 1) {\n                // We are the right child. Our sibling is the \"rightmost\" \"left-child\" node\n                // that has two non-empty children → sibling is `tree.branch[i]`\n                current = MerkleMath.getParent(tree.branch[i], current);\n            } else {\n                // We are the left child. Our sibling does not exist yet → sibling is EMPTY\n                current = MerkleMath.getParent(current, bytes32(0));\n            }\n            // Get the parent index, and go to the next tree level\n            count \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    // ══════════════════════════════════════════════ HISTORICAL TREE ══════════════════════════════════════════════════\n\n    /// @notice Initializes the historical roots for the tree by inserting an empty root.\n    // solhint-disable-next-line ordering\n    function initializeRoots(HistoricalTree storage tree) internal returns (bytes32 savedRoot) {\n        // This should only be called once, when the contract is initialized\n        assert(tree.roots.length == 0);\n        // Save root for empty merkle tree: bytes32(0)\n        tree.roots.push(savedRoot);\n    }\n\n    /// @notice Inserts a new leaf into the merkle tree.\n    /// @dev Reverts if tree is full.\n    /// @param node         Element to insert into tree\n    /// @return newRoot     Merkle root after the leaf was inserted\n    function insert(HistoricalTree storage tree, bytes32 node) internal returns (bytes32 newRoot) {\n        // Tree count after the new leaf will be inserted (we store roots[0] as root of empty tree)\n        uint256 newCount = tree.roots.length;\n        tree.tree.insertBase(newCount, node);\n        // Save the new root\n        newRoot = tree.tree.rootBase(newCount);\n        tree.roots.push(newRoot);\n    }\n\n    /// @notice Returns the historical root of the merkle tree.\n    /// @dev Reverts if not enough leafs have been inserted.\n    /// @param count            Amount of leafs in the tree at some point of time\n    /// @return historicalRoot  Merkle root after `count` leafs were inserted\n    function root(HistoricalTree storage tree, uint256 count) internal view returns (bytes32 historicalRoot) {\n        if (count \u003e= tree.roots.length) revert NotEnoughLeafs();\n        return tree.roots[count];\n    }\n\n    // ═══════════════════════════════════════════════ DYNAMIC TREE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Updates the value for the leaf with the given index in the Dynamic Merkle Tree.\n     * @dev Will revert if incorrect proof of inclusion for old value is supplied.\n     * @param tree          Dynamic merkle tree\n     * @param index         Index of the leaf to update\n     * @param oldValue      Previous value of the leaf\n     * @param branch        Proof of inclusion of previous value into the tree\n     * @param newValue      New leaf value to assign\n     * @return newRoot      New value for the Merkle Root after the leaf is updated\n     */\n    function update(\n        DynamicTree storage tree,\n        uint256 index,\n        bytes32 oldValue,\n        bytes32[] memory branch,\n        bytes32 newValue\n    ) internal returns (bytes32 newRoot) {\n        // Check that the old value + proof result in a correct root\n        if (MerkleMath.proofRoot(index, oldValue, branch, AGENT_TREE_HEIGHT) != tree.root) {\n            revert LeafNotProven();\n        }\n        // New root is new value + the same proof (values for sibling nodes are not updated)\n        newRoot = MerkleMath.proofRoot(index, newValue, branch, AGENT_TREE_HEIGHT);\n        // Write the new root\n        tree.root = newRoot;\n    }\n}\n\n// contracts/libs/stack/Tips.sol\n\n/// Tips is encoded data with \"tips paid for sending a base message\".\n/// Note: even though uint256 is also an underlying type for MemView, Tips is stored ON STACK.\ntype Tips is uint256;\n\nusing TipsLib for Tips global;\n\n/// # Tips\n/// Library for formatting _the tips part_ of _the base messages_.\n///\n/// ## How the tips are awarded\n/// Tips are paid for sending a base message, and are split across all the agents that\n/// made the message execution on destination chain possible.\n/// ### Summit tips\n/// Split between:\n///     - Guard posting a snapshot with state ST_G for the origin chain.\n///     - Notary posting a snapshot SN_N using ST_G. This creates attestation A.\n///     - Notary posting a message receipt after it is executed on destination chain.\n/// ### Attestation tips\n/// Paid to:\n///     - Notary posting attestation A to destination chain.\n/// ### Execution tips\n/// Paid to:\n///     - First executor performing a valid execution attempt (correct proofs, optimistic period over),\n///      using attestation A to prove message inclusion on origin chain, whether the recipient reverted or not.\n/// ### Delivery tips.\n/// Paid to:\n///     - Executor who successfully executed the message on destination chain.\n///\n/// ## Tips encoding\n/// - Tips occupy a single storage word, and thus are stored on stack instead of being stored in memory.\n/// - The actual tip values should be determined by multiplying stored values by divided by TIPS_MULTIPLIER=2**32.\n/// - Tips are packed into a single word of storage, while allowing real values up to ~8*10**28 for every tip category.\n/// \u003e The only downside is that the \"real tip values\" are now multiplies of ~4*10**9, which should be fine even for\n/// the chains with the most expensive gas currency.\n/// # Tips stack layout (from highest bits to lowest)\n///\n/// | Position   | Field          | Type   | Bytes | Description                                                |\n/// | ---------- | -------------- | ------ | ----- | ---------------------------------------------------------- |\n/// | (032..024] | summitTip      | uint64 | 8     | Tip for agents interacting with Summit contract            |\n/// | (024..016] | attestationTip | uint64 | 8     | Tip for Notary posting attestation to Destination contract |\n/// | (016..008] | executionTip   | uint64 | 8     | Tip for valid execution attempt on destination chain       |\n/// | (008..000] | deliveryTip    | uint64 | 8     | Tip for successful message delivery on destination chain   |\n\nlibrary TipsLib {\n    using SafeCast for uint256;\n\n    /// @dev Amount of bits to shift to summitTip field\n    uint256 private constant SHIFT_SUMMIT_TIP = 24 * 8;\n    /// @dev Amount of bits to shift to attestationTip field\n    uint256 private constant SHIFT_ATTESTATION_TIP = 16 * 8;\n    /// @dev Amount of bits to shift to executionTip field\n    uint256 private constant SHIFT_EXECUTION_TIP = 8 * 8;\n\n    // ═══════════════════════════════════════════════════ TIPS ════════════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips with the given fields\n    /// @param summitTip_        Tip for agents interacting with Summit contract, divided by TIPS_MULTIPLIER\n    /// @param attestationTip_   Tip for Notary posting attestation to Destination contract, divided by TIPS_MULTIPLIER\n    /// @param executionTip_     Tip for valid execution attempt on destination chain, divided by TIPS_MULTIPLIER\n    /// @param deliveryTip_      Tip for successful message delivery on destination chain, divided by TIPS_MULTIPLIER\n    function encodeTips(uint64 summitTip_, uint64 attestationTip_, uint64 executionTip_, uint64 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // forgefmt: disable-next-item\n        return Tips.wrap(\n            uint256(summitTip_) \u003c\u003c SHIFT_SUMMIT_TIP |\n            uint256(attestationTip_) \u003c\u003c SHIFT_ATTESTATION_TIP |\n            uint256(executionTip_) \u003c\u003c SHIFT_EXECUTION_TIP |\n            uint256(deliveryTip_)\n        );\n    }\n\n    /// @notice Convenience function to encode tips with uint256 values.\n    function encodeTips256(uint256 summitTip_, uint256 attestationTip_, uint256 executionTip_, uint256 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // In practice, the tips amounts are not supposed to be higher than 2**96, and with 32 bits of granularity\n        // using uint64 is enough to store the values. However, we still check for overflow just in case.\n        // TODO: consider using Number type to store the tips values.\n        return encodeTips({\n            summitTip_: (summitTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            attestationTip_: (attestationTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            executionTip_: (executionTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            deliveryTip_: (deliveryTip_ \u003e\u003e TIPS_GRANULARITY).toUint64()\n        });\n    }\n\n    /// @notice Wraps the padded encoded tips into a Tips-typed value.\n    /// @dev There is no actual padding here, as the underlying type is already uint256,\n    /// but we include this function for consistency and to be future-proof, if tips will eventually use anything\n    /// smaller than uint256.\n    function wrapPadded(uint256 paddedTips) internal pure returns (Tips) {\n        return Tips.wrap(paddedTips);\n    }\n\n    /**\n     * @notice Returns a formatted Tips payload specifying empty tips.\n     * @return Formatted tips\n     */\n    function emptyTips() internal pure returns (Tips) {\n        return Tips.wrap(0);\n    }\n\n    /// @notice Returns tips's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Tips tips) internal pure returns (bytes32 hashedTips) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store tips in scratch space\n            mstore(0, tips)\n            // Compute hash of tips padded to 32 bytes\n            hashedTips := keccak256(0, 32)\n        }\n    }\n\n    // ═══════════════════════════════════════════════ TIPS SLICING ════════════════════════════════════════════════════\n\n    /// @notice Returns summitTip field\n    function summitTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_SUMMIT_TIP);\n    }\n\n    /// @notice Returns attestationTip field\n    function attestationTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_ATTESTATION_TIP);\n    }\n\n    /// @notice Returns executionTip field\n    function executionTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_EXECUTION_TIP);\n    }\n\n    /// @notice Returns deliveryTip field\n    function deliveryTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips));\n    }\n\n    // ════════════════════════════════════════════════ TIPS VALUE ═════════════════════════════════════════════════════\n\n    /// @notice Returns total value of the tips payload.\n    /// This is the sum of the encoded values, scaled up by TIPS_MULTIPLIER\n    function value(Tips tips) internal pure returns (uint256 value_) {\n        value_ = uint256(tips.summitTip()) + tips.attestationTip() + tips.executionTip() + tips.deliveryTip();\n        value_ \u003c\u003c= TIPS_GRANULARITY;\n    }\n\n    /// @notice Increases the delivery tip to match the new value.\n    function matchValue(Tips tips, uint256 newValue) internal pure returns (Tips newTips) {\n        uint256 oldValue = tips.value();\n        if (newValue \u003c oldValue) revert TipsValueTooLow();\n        // We want to increase the delivery tip, while keeping the other tips the same\n        unchecked {\n            uint256 delta = (newValue - oldValue) \u003e\u003e TIPS_GRANULARITY;\n            // `delta` fits into uint224, as TIPS_GRANULARITY is 32, so this never overflows uint256.\n            // In practice, this will never overflow uint64 as well, but we still check it just in case.\n            if (delta + tips.deliveryTip() \u003e type(uint64).max) revert TipsOverflow();\n            // Delivery tips occupy lowest 8 bytes, so we can just add delta to the tips value\n            // to effectively increase the delivery tip (knowing that delta fits into uint64).\n            newTips = Tips.wrap(Tips.unwrap(tips) + delta);\n        }\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    function __Ownable_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable_init_unchained() internal onlyInitializing {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n    function __Ownable2Step_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable2Step_init_unchained() internal onlyInitializing {\n    }\n    address private _pendingOwner;\n\n    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Returns the address of the pending owner.\n     */\n    function pendingOwner() public view virtual returns (address) {\n        return _pendingOwner;\n    }\n\n    /**\n     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual override onlyOwner {\n        _pendingOwner = newOwner;\n        emit OwnershipTransferStarted(owner(), newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual override {\n        delete _pendingOwner;\n        super._transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev The new owner accepts the ownership transfer.\n     */\n    function acceptOwnership() public virtual {\n        address sender = _msgSender();\n        require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n        _transferOwnership(sender);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// contracts/libs/memory/State.sol\n\n/// State is a memory view over a formatted state payload.\ntype State is uint256;\n\nusing StateLib for State global;\n\n/// # State\n/// State structure represents the state of Origin contract at some point of time.\n/// - State is structured in a way to track the updates of the Origin Merkle Tree.\n/// - State includes root of the Origin Merkle Tree, origin domain and some additional metadata.\n/// ## Origin Merkle Tree\n/// Hash of every sent message is inserted in the Origin Merkle Tree, which changes\n/// the value of Origin Merkle Root (which is the root for the mentioned tree).\n/// - Origin has a single Merkle Tree for all messages, regardless of their destination domain.\n/// - This leads to Origin state being updated if and only if a message was sent in a block.\n/// - Origin contract is a \"source of truth\" for states: a state is considered \"valid\" in its Origin,\n/// if it matches the state of the Origin contract after the N-th (nonce) message was sent.\n///\n/// # Memory layout of State fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                    |\n/// | ---------- | ----------- | ------- | ----- | ------------------------------ |\n/// | [000..032) | root        | bytes32 | 32    | Root of the Origin Merkle Tree |\n/// | [032..036) | origin      | uint32  | 4     | Domain where Origin is located |\n/// | [036..040) | nonce       | uint32  | 4     | Amount of sent messages        |\n/// | [040..045) | blockNumber | uint40  | 5     | Block of last sent message     |\n/// | [045..050) | timestamp   | uint40  | 5     | Time of last sent message      |\n/// | [050..062) | gasData     | uint96  | 12    | Gas data for the chain         |\n///\n/// @dev State could be used to form a Snapshot to be signed by a Guard or a Notary.\nlibrary StateLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_ROOT = 0;\n    uint256 private constant OFFSET_ORIGIN = 32;\n    uint256 private constant OFFSET_NONCE = 36;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 40;\n    uint256 private constant OFFSET_TIMESTAMP = 45;\n    uint256 private constant OFFSET_GAS_DATA = 50;\n\n    // ═══════════════════════════════════════════════════ STATE ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted State payload with provided fields\n     * @param root_         New merkle root\n     * @param origin_       Domain of Origin's chain\n     * @param nonce_        Nonce of the merkle root\n     * @param blockNumber_  Block number when root was saved in Origin\n     * @param timestamp_    Block timestamp when root was saved in Origin\n     * @param gasData_      Gas data for the chain\n     * @return Formatted state\n     */\n    function formatState(\n        bytes32 root_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_,\n        GasData gasData_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(root_, origin_, nonce_, blockNumber_, timestamp_, gasData_);\n    }\n\n    /**\n     * @notice Returns a State view over the given payload.\n     * @dev Will revert if the payload is not a state.\n     */\n    function castToState(bytes memory payload) internal pure returns (State) {\n        return castToState(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a State view.\n     * @dev Will revert if the memory view is not over a state.\n     */\n    function castToState(MemView memView) internal pure returns (State) {\n        if (!isState(memView)) revert UnformattedState();\n        return State.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted State.\n    function isState(MemView memView) internal pure returns (bool) {\n        return memView.len() == STATE_LENGTH;\n    }\n\n    /// @notice Returns the hash of a State, that could be later signed by a Guard to signal\n    /// that the state is invalid.\n    function hashInvalid(State state) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(stateInvalidSalt, keccak(state))\n        return state.unwrap().keccakSalted(STATE_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(State state) internal pure returns (MemView) {\n        return MemView.wrap(State.unwrap(state));\n    }\n\n    /// @notice Compares two State structures.\n    function equals(State a, State b) internal pure returns (bool) {\n        // Length of a State payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═══════════════════════════════════════════════ STATE HASHING ═══════════════════════════════════════════════════\n\n    /// @notice Returns the hash of the State.\n    /// @dev We are using the Merkle Root of a tree with two leafs (see below) as state hash.\n    function leaf(State state) internal pure returns (bytes32) {\n        (bytes32 leftLeaf_, bytes32 rightLeaf_) = state.subLeafs();\n        // Final hash is the parent of these leafs\n        return keccak256(bytes.concat(leftLeaf_, rightLeaf_));\n    }\n\n    /// @notice Returns \"sub-leafs\" of the State. Hash of these \"sub leafs\" is going to be used\n    /// as a \"state leaf\" in the \"Snapshot Merkle Tree\".\n    /// This enables proving that leftLeaf = (root, origin) was a part of the \"Snapshot Merkle Tree\",\n    /// by combining `rightLeaf` with the remainder of the \"Snapshot Merkle Proof\".\n    function subLeafs(State state) internal pure returns (bytes32 leftLeaf_, bytes32 rightLeaf_) {\n        MemView memView = state.unwrap();\n        // Left leaf is (root, origin)\n        leftLeaf_ = memView.prefix({len_: OFFSET_NONCE}).keccak();\n        // Right leaf is (metadata), or (nonce, blockNumber, timestamp)\n        rightLeaf_ = memView.sliceFrom({index_: OFFSET_NONCE}).keccak();\n    }\n\n    /// @notice Returns the left \"sub-leaf\" of the State.\n    function leftLeaf(bytes32 root_, uint32 origin_) internal pure returns (bytes32) {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(root_, origin_));\n    }\n\n    /// @notice Returns the right \"sub-leaf\" of the State.\n    function rightLeaf(uint32 nonce_, uint40 blockNumber_, uint40 timestamp_, GasData gasData_)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(nonce_, blockNumber_, timestamp_, gasData_));\n    }\n\n    // ═══════════════════════════════════════════════ STATE SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns a historical Merkle root from the Origin contract.\n    function root(State state) internal pure returns (bytes32) {\n        return state.unwrap().index({index_: OFFSET_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns domain of chain where the Origin contract is deployed.\n    function origin(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns nonce of Origin contract at the time, when `root` was the Merkle root.\n    function nonce(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when `root` was saved in Origin.\n    function blockNumber(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when `root` was saved in Origin.\n    /// @dev This is the timestamp according to the origin chain.\n    function timestamp(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n\n    /// @notice Returns gas data for the chain.\n    function gasData(State state) internal pure returns (GasData) {\n        return GasDataLib.wrapGasData(state.unwrap().indexUint({index_: OFFSET_GAS_DATA, bytes_: GAS_DATA_LENGTH}));\n    }\n}\n\n// contracts/libs/memory/BaseMessage.sol\n\n/// BaseMessage is a memory view over the base message supported by Origin-Destination\ntype BaseMessage is uint256;\n\nusing BaseMessageLib for BaseMessage global;\n\n/// BaseMessage structure represents a base message sent via the Origin-Destination contracts.\n/// - It only contains data relevant to the base message, the rest of data is encoded in the message header.\n/// - `sender` and `recipient` for EVM chains are EVM addresses casted to bytes32, while preserving left-alignment.\n/// - `tips` and `request` parameters are specified by a message sender\n/// \u003e Origin will calculate minimum tips for given request and content length, and will reject messages with tips\n/// lower than that.\n///\n/// # Memory layout of BaseMessage fields\n///\n/// | Position   | Field     | Type    | Bytes | Description                            |\n/// | ---------- | --------- | ------- | ----- | -------------------------------------- |\n/// | [000..032) | tips      | uint256 | 32    | Encoded tips paid on origin chain      |\n/// | [032..064) | sender    | bytes32 | 32    | Sender address on origin chain         |\n/// | [064..096) | recipient | bytes32 | 32    | Recipient address on destination chain |\n/// | [096..116) | request   | uint160 | 20    | Encoded request for message execution  |\n/// | [104..AAA) | content   | bytes   | ??    | Content to be passed to recipient      |\nlibrary BaseMessageLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_TIPS = 0;\n    uint256 private constant OFFSET_SENDER = 32;\n    uint256 private constant OFFSET_RECIPIENT = 64;\n    uint256 private constant OFFSET_REQUEST = OFFSET_RECIPIENT + TIPS_LENGTH;\n    uint256 private constant OFFSET_CONTENT = OFFSET_REQUEST + REQUEST_LENGTH;\n\n    // ═══════════════════════════════════════════════ BASE MESSAGE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted BaseMessage payload with provided fields.\n     * @param tips_         Encoded tips information\n     * @param sender_       Sender address on origin chain\n     * @param recipient_    Recipient address on destination chain\n     * @param request_      Encoded request for message execution\n     * @param content_      Raw content to be passed to recipient on destination chain\n     * @return Formatted base message\n     */\n    function formatBaseMessage(Tips tips_, bytes32 sender_, bytes32 recipient_, Request request_, bytes memory content_)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return abi.encodePacked(tips_, sender_, recipient_, request_, content_);\n    }\n\n    /**\n     * @notice Returns a BaseMessage view over the given payload.\n     * @dev Will revert if the payload is not a base message.\n     */\n    function castToBaseMessage(bytes memory payload) internal pure returns (BaseMessage) {\n        return castToBaseMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a BaseMessage view.\n     * @dev Will revert if the memory view is not over a base message payload.\n     */\n    function castToBaseMessage(MemView memView) internal pure returns (BaseMessage) {\n        if (!isBaseMessage(memView)) revert UnformattedBaseMessage();\n        return BaseMessage.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted BaseMessage.\n    function isBaseMessage(MemView memView) internal pure returns (bool) {\n        // Check if sender, recipient, tips fields exist\n        return (memView.len() \u003e= OFFSET_CONTENT);\n        // Content could be empty, so we don't check that\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(BaseMessage baseMessage) internal pure returns (MemView) {\n        return MemView.wrap(BaseMessage.unwrap(baseMessage));\n    }\n\n    /// @notice Returns baseMessage's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        // We hash \"tips\" and \"everything but tips\" to make tips proofs easier to verify\n        return MerkleMath.getParent(baseMessage.tips().leaf(), baseMessage.bodyLeaf());\n    }\n\n    /// @notice Returns hash for the \"everything but tips\" part of the base message.\n    function bodyLeaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_SENDER}).keccak();\n    }\n\n    // ═══════════════════════════════════════════ BASE MESSAGE SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips paid on origin chain.\n    function tips(BaseMessage baseMessage) internal pure returns (Tips) {\n        return TipsLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_TIPS, bytes_: TIPS_LENGTH})));\n    }\n\n    /// @notice Returns sender address on origin chain.\n    function sender(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_SENDER, bytes_: 32});\n    }\n\n    /// @notice Returns recipient address on destination chain.\n    function recipient(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_RECIPIENT, bytes_: 32});\n    }\n\n    /// @notice Returns an encoded request for message execution on destination chain.\n    function request(BaseMessage baseMessage) internal pure returns (Request) {\n        return RequestLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_REQUEST, bytes_: REQUEST_LENGTH})));\n    }\n\n    /// @notice Returns an untyped memory view over the content to be passed to recipient.\n    function content(BaseMessage baseMessage) internal pure returns (MemView) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_CONTENT});\n    }\n}\n\n// contracts/base/MessagingBase.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for all messaging contracts.\n * - Provides context on the local chain's domain.\n * - Provides ownership functionality.\n * - Will be providing pausing functionality when it is implemented.\n */\nabstract contract MessagingBase is MultiCallable, Versioned, Ownable2StepUpgradeable {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @notice Domain of the local chain, set once upon contract creation\n    uint32 public immutable localDomain;\n    // @notice Domain of the Synapse chain, set once upon contract creation\n    uint32 public immutable synapseDomain;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev gap for upgrade safety\n    uint256[50] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    constructor(string memory version_, uint32 synapseDomain_) Versioned(version_) {\n        localDomain = ChainContext.chainId();\n        synapseDomain = synapseDomain_;\n    }\n\n    // TODO: Implement pausing\n\n    /**\n     * @dev Should be impossible to renounce ownership;\n     * we override OpenZeppelin OwnableUpgradeable's\n     * implementation of renounceOwnership to make it a no-op\n     */\n    function renounceOwnership() public override onlyOwner {} //solhint-disable-line no-empty-blocks\n}\n\n// contracts/libs/memory/Message.sol\n\n/// Message is a memory over over a formatted message payload.\ntype Message is uint256;\n\nusing MessageLib for Message global;\n\n/// Library for formatting the various messages supported by Origin and Destination.\n///\n/// # Message memory layout\n///\n/// | Position   | Field  | Type    | Bytes | Description                                             |\n/// | ---------- | ------ | ------- | ----- | ------------------------------------------------------- |\n/// | [000..017) | header | uint136 | 17    | Encoded general routing information for the message     |\n/// | [017..AAA) | body   | bytes   | ??    | Formatted payload (according to flag) with message body |\nlibrary MessageLib {\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MemViewLib for bytes;\n    using HeaderLib for MemView;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_HEADER = 0;\n    uint256 private constant OFFSET_BODY = OFFSET_HEADER + HEADER_LENGTH;\n\n    // ══════════════════════════════════════════════════ MESSAGE ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns formatted message with provided fields.\n     * @param header_   Encoded general routing information for the message\n     * @param body_     Formatted payload (according to flag) with message body\n     * @return Formatted message\n     */\n    function formatMessage(Header header_, bytes memory body_) internal pure returns (bytes memory) {\n        return abi.encodePacked(header_, body_);\n    }\n\n    /**\n     * @notice Returns a Message view over for the given payload.\n     * @dev Will revert if the payload is not a message payload.\n     */\n    function castToMessage(bytes memory payload) internal pure returns (Message) {\n        return castToMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Message view.\n     * @dev Will revert if the memory view is not over a message payload.\n     */\n    function castToMessage(MemView memView) internal pure returns (Message) {\n        if (!isMessage(memView)) revert UnformattedMessage();\n        return Message.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Message.\n     */\n    function isMessage(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Check if headers exist in the payload\n        if (length \u003c OFFSET_BODY) return false;\n        // Check that Header is valid\n        uint256 paddedHeader = _header(memView);\n        if (!HeaderLib.isHeader(paddedHeader)) return false;\n        // Check that body is formatted according to the flag\n        // Only Base/Manager message flags exist\n        if (HeaderLib.wrapPadded(paddedHeader).flag() == MessageFlag.Base) {\n            // Check if body is a formatted base message\n            return _body(memView).isBaseMessage();\n        } else {\n            // Check if body is a formatted calldata for AgentManager call\n            return _body(memView).isCallData();\n        }\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Message message) internal pure returns (MemView) {\n        return MemView.wrap(Message.unwrap(message));\n    }\n\n    /// @notice Returns message's hash: a leaf to be inserted in the Merkle tree.\n    function leaf(Message message) internal pure returns (bytes32) {\n        // We hash header and body separately to make message proofs easier to verify\n        Header header_ = message.header();\n        // Only Base/Manager message flags exist\n        if (header_.flag() == MessageFlag.Base) {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToBaseMessage().leaf());\n        } else {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToCallData().leaf());\n        }\n    }\n\n    // ══════════════════════════════════════════════ MESSAGE SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns message's encoded header field.\n    function header(Message message) internal pure returns (Header) {\n        return HeaderLib.wrapPadded((message.unwrap().indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH})));\n    }\n\n    /// @notice Returns message's body field as an untyped memory view.\n    function body(Message message) internal pure returns (MemView) {\n        MemView memView = message.unwrap();\n        return _body(memView);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns message's padded header without checking that it is a valid header.\n    function _header(MemView memView) private pure returns (uint256) {\n        return memView.indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH});\n    }\n\n    /// @dev Returns an untyped memory view over the body field without checking\n    /// if the whole payload or the body are properly formatted.\n    function _body(MemView memView) private pure returns (MemView) {\n        return memView.sliceFrom({index_: OFFSET_BODY});\n    }\n}\n\n// contracts/base/AgentSecured.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for messaging contracts that are secured by the agent manager.\n * `AgentSecured` relies on `AgentManager` to provide the following functionality:\n * - Keep track of agents and their statuses.\n * - Pass agent-signed statements that were verified by the agent manager.\n * - These statements are considered valid indefinitely, unless the agent is disputed.\n * - Disputes are opened and resolved by the agent manager.\n * \u003e `AgentSecured` implementation should never use statements signed by agents that are disputed.\n */\nabstract contract AgentSecured is MessagingBase, IAgentSecured {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    address public immutable agentManager;\n\n    /// @inheritdoc IAgentSecured\n    address public immutable inbox;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    // (agent index =\u003e their dispute status: flag, openedAt, resolvedAt)\n    mapping(uint32 =\u003e DisputeStatus) internal _disputes;\n\n    /// @dev gap for upgrade safety\n    uint256[49] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    modifier onlyAgentManager() {\n        if (msg.sender != agentManager) revert CallerNotAgentManager();\n        _;\n    }\n\n    modifier onlyInbox() {\n        if (msg.sender != inbox) revert CallerNotInbox();\n        _;\n    }\n\n    constructor(string memory version_, uint32 synapseDomain_, address agentManager_, address inbox_)\n        MessagingBase(version_, synapseDomain_)\n    {\n        agentManager = agentManager_;\n        inbox = inbox_;\n    }\n\n    // ════════════════════════════════════════════ ONLY AGENT MANAGER ═════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external onlyAgentManager {\n        uint40 openedAt = ChainContext.blockTimestamp();\n        DisputeStatus memory status = DisputeStatus({flag: DisputeFlag.Pending, openedAt: openedAt, resolvedAt: 0});\n        _disputes[guardIndex] = status;\n        _disputes[notaryIndex] = status;\n    }\n\n    /// @inheritdoc IAgentSecured\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external onlyAgentManager {\n        // Update the dispute status of the slashed agent first.\n        uint40 resolvedAt = ChainContext.blockTimestamp();\n        _disputes[slashedIndex].flag = DisputeFlag.Slashed;\n        _disputes[slashedIndex].resolvedAt = resolvedAt;\n        // Mark the rival agent as not disputed, if there was an ongoing dispute.\n        if (rivalIndex != 0) {\n            _disputes[rivalIndex].flag = DisputeFlag.None;\n            _disputes[rivalIndex].resolvedAt = resolvedAt;\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function agentStatus(address agent) external view returns (AgentStatus memory) {\n        return _agentStatus(agent);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status) {\n        return _getAgent(index);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory) {\n        return _disputes[agentIndex];\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns status of the given agent: (flag, domain, index).\n    function _agentStatus(address agent) internal view returns (AgentStatus memory) {\n        return IAgentManager(agentManager).agentStatus(agent);\n    }\n\n    /// @dev Returns agent and their status for a given agent index. Returns zero values for non existing indexes.\n    function _getAgent(uint256 index) internal view returns (address agent, AgentStatus memory status) {\n        return IAgentManager(agentManager).getAgent(index);\n    }\n\n    /// @dev Checks if a Dispute exists for the given Notary. This function returns true, if\n    /// Notary is in ongoing Dispute, or if Dispute was resolved not in Notary's favor.\n    /// In both cases we can't trust Notary's data.\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeExists(uint32 notaryIndex) internal view returns (bool) {\n        return _disputes[notaryIndex].flag != DisputeFlag.None;\n    }\n\n    /// @dev Checks if a Notary recently won a Dispute and is still in the \"post-dispute\" timeout period.\n    /// In this period we still can't trust Notary's data, though we can optimistically assume that\n    /// that the data will be correct after the timeout (assuming no new Disputes are opened).\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeTimeout(uint32 notaryIndex) internal view returns (bool) {\n        DisputeStatus memory status = _disputes[notaryIndex];\n        // Exit early if Notary is in ongoing Dispute / slashed.\n        if (status.flag != DisputeFlag.None) return false;\n        // Check if Notary has been in any Dispute at all.\n        if (status.openedAt == 0) return false;\n        // Otherwise check if the Dispute timeout is still active.\n        return block.timestamp \u003c status.resolvedAt + DISPUTE_TIMEOUT_NOTARY;\n    }\n}\n\n// contracts/hubs/StateHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StateHub` is a parent contract for `Origin`. It is responsible for the following:\n/// - Keeping track of the historical Origin Merkle Tree containing all the message hashes.\n/// - Keeping track of the historical Origin States, as well as verifying their validity.\nabstract contract StateHub is AgentSecured, StateHubEvents, IStateHub {\n    using SafeCast for uint256;\n    using StateLib for bytes;\n\n    struct OriginState {\n        uint40 blockNumber;\n        uint40 timestamp;\n        GasData gasData;\n    }\n    // Bits left for tight packing: 80\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Historical Merkle Tree\n    /// Note: Takes two storage slots\n    HistoricalTree private _tree;\n\n    /// @dev All historical contract States\n    OriginState[] private _originStates;\n\n    /// @dev gap for upgrade safety\n    uint256[47] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IStateHub\n    function isValidState(bytes memory statePayload) external view returns (bool isValid) {\n        // This will revert if payload is not a formatted state\n        State state = statePayload.castToState();\n        return _isValidState(state);\n    }\n\n    /// @inheritdoc IStateHub\n    function statesAmount() external view returns (uint256) {\n        return _originStates.length;\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestLatestState() external view returns (bytes memory stateData) {\n        // This never underflows, assuming the contract was initialized\n        return suggestState(_nextNonce() - 1);\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestState(uint32 nonce) public view returns (bytes memory stateData) {\n        // This will revert if nonce is out of range\n        bytes32 root = _tree.root(nonce);\n        return _formatOriginState(_originStates[nonce], root, localDomain, nonce);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Initializes the saved states list by inserting a state for an empty Merkle Tree.\n    function _initializeStates() internal {\n        // This should only be called once, when the contract is initialized\n        // This will revert if _tree.roots is non-empty\n        bytes32 savedRoot = _tree.initializeRoots();\n        // Save root for empty merkle _tree with block number and timestamp of initialization\n        _saveState(savedRoot, _toOriginState());\n    }\n\n    /// @dev Inserts leaf into the Merkle Tree and saves the updated origin State.\n    function _insertAndSave(bytes32 leaf) internal {\n        bytes32 newRoot = _tree.insert(leaf);\n        _saveState(newRoot, _toOriginState());\n    }\n\n    /// @dev Saves an updated state of the Origin contract\n    function _saveState(bytes32 root, OriginState memory state) internal {\n        uint32 nonce = _nextNonce();\n        _originStates.push(state);\n        // Emit event with raw state data\n        emit StateSaved(_formatOriginState(state, root, localDomain, nonce));\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns nonce of the next sent message: the amount of saved States so far.\n    /// This always equals to \"total amount of sent messages\" plus 1.\n    function _nextNonce() internal view returns (uint32) {\n        // TODO: consider using more than 32 bits for origin nonces\n        return _originStates.length.toUint32();\n    }\n\n    /// @dev Checks if a state is valid, i.e. if it matches the historical one.\n    /// Reverts, if state refers to another Origin contract.\n    function _isValidState(State state) internal view returns (bool) {\n        // Check if state refers to this contract\n        if (state.origin() != localDomain) revert IncorrectOriginDomain();\n        // Check if nonce exists\n        uint32 nonce = state.nonce();\n        if (nonce \u003e= _originStates.length) return false;\n        // Check if state root matches the historical one\n        if (state.root() != _tree.root(nonce)) return false;\n        // Check if state metadata matches the historical one\n        return _areEqual(state, _originStates[nonce]);\n    }\n\n    // ═════════════════════════════════════════════ STRUCT FORMATTING ═════════════════════════════════════════════════\n\n    /// @dev Returns a formatted payload for a stored OriginState.\n    function _formatOriginState(OriginState memory originState, bytes32 root, uint32 origin, uint32 nonce)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return StateLib.formatState({\n            root_: root,\n            origin_: origin,\n            nonce_: nonce,\n            blockNumber_: originState.blockNumber,\n            timestamp_: originState.timestamp,\n            gasData_: originState.gasData\n        });\n    }\n\n    /// @dev Child contract should implement the logic for getting the current gas data from the gas oracle\n    /// to be saved as part of the Origin State.\n    // solhint-disable-next-line ordering\n    function _fetchGasData() internal view virtual returns (GasData);\n\n    /// @dev Returns a OriginState struct to save in the contract.\n    function _toOriginState() internal view returns (OriginState memory originState) {\n        originState.blockNumber = ChainContext.blockNumber();\n        originState.timestamp = ChainContext.blockTimestamp();\n        originState.gasData = _fetchGasData();\n    }\n\n    /// @dev Checks that a state and its Origin representation are equal.\n    function _areEqual(State state, OriginState memory originState) internal pure returns (bool) {\n        return state.blockNumber() == originState.blockNumber \u0026\u0026 state.timestamp() == originState.timestamp;\n    }\n}\n\n// contracts/Origin.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Origin` contract is used for sending messages to remote chains. It is done\n/// by inserting the message hashes into the Origin Merkle, which makes it possible to\n/// prove that message was sent using the Merkle proof against the Origin Merkle Root. This essentially\n/// compresses the list of messages into a single 32-byte value that needs to be stored on the destination chain.\n/// `Origin` is responsible for the following:\n/// - Formatting the sent message payloads, and inserting their hashes into the Origin Merkle Tree.\n/// - Keeping track of its own historical states (see parent contract `StateHub`).\n/// - Enforcing minimum tip values for sent base messages based on the provided execution requests.\n/// - Distributing the collected tips upon request from a local `AgentManager` contract.\ncontract Origin is StateHub, OriginEvents, InterfaceOrigin {\n    using MemViewLib for bytes;\n    using MessageLib for bytes;\n    using TipsLib for bytes;\n    using TypeCasts for address;\n\n    address public immutable gasOracle;\n\n    modifier onlyRemoteDestination(uint32 destination) {\n        if (destination == localDomain) revert IncorrectDestinationDomain();\n        _;\n    }\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_, address gasOracle_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {\n        gasOracle = gasOracle_;\n    }\n\n    /// @notice Initializes Origin contract:\n    /// - msg.sender is set as contract owner\n    /// - State of \"empty merkle tree\" is saved\n    function initialize() external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize \"states\": state of an \"empty merkle tree\" is saved\n        _initializeStates();\n    }\n\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable onlyRemoteDestination(destination) returns (uint32 messageNonce, bytes32 messageHash) {\n        // Check that content is not too large\n        if (content.length \u003e MAX_CONTENT_BYTES) revert ContentLengthTooBig();\n        // This will revert if msg.value is lower than value of minimum tips\n        Tips tips = _getMinimumTips(destination, paddedRequest, content.length).matchValue(msg.value);\n        Request request = RequestLib.wrapPadded(paddedRequest);\n        // Format the BaseMessage body\n        bytes memory body = BaseMessageLib.formatBaseMessage({\n            sender_: msg.sender.addressToBytes32(),\n            recipient_: recipient,\n            tips_: tips,\n            request_: request,\n            content_: content\n        });\n        // Send the message\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Base, body);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        onlyAgentManager\n        onlyRemoteDestination(destination)\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // AgentManager (checked via modifier) is responsible for constructing the calldata payload correctly.\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Manager, payload);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function withdrawTips(address recipient, uint256 amount) external onlyAgentManager {\n        if (address(this).balance \u003c amount) revert InsufficientEthBalance();\n        (bool success,) = recipient.call{value: amount}(\"\");\n        if (!success) revert EthTransferFailed();\n        emit TipWithdrawalCompleted(recipient, amount);\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue)\n    {\n        return _getMinimumTips(destination, paddedRequest, contentLength).value();\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Sends the given message to the specified destination. Message hash is inserted\n    /// into the Origin Merkle Tree, which will enable message execution on destination chain.\n    function _sendMessage(uint32 destination, uint32 optimisticPeriod, MessageFlag flag, bytes memory body)\n        internal\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // Format the message header\n        messageNonce = _nextNonce();\n        Header header = flag.encodeHeader({\n            origin_: localDomain,\n            nonce_: messageNonce,\n            destination_: destination,\n            optimisticPeriod_: optimisticPeriod\n        });\n        // Format the full message payload\n        bytes memory msgPayload = MessageLib.formatMessage(header, body);\n        // Insert new leaf into the Origin Merkle Tree and save the updated state\n        messageHash = msgPayload.castToMessage().leaf();\n        _insertAndSave(messageHash);\n        // Emit event with message information\n        emit Sent(messageHash, messageNonce, destination, msgPayload);\n        // Update the gas oracle data. We do this after the provided tips are checked so that\n        // the provided message is sent in the event that the gas oracle data is updated to a higher value.\n        InterfaceGasOracle(gasOracle).updateGasData(destination);\n        // TODO: consider doing this before the message is sent, while adjusting GasOracle.getMinimumTips() to\n        // use the pending gas oracle data.\n    }\n\n    /// @dev Returns the minimum tips for sending a message to the given destination with the given request and content.\n    function _getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        internal\n        view\n        returns (Tips)\n    {\n        return\n            TipsLib.wrapPadded(InterfaceGasOracle(gasOracle).getMinimumTips(destination, paddedRequest, contentLength));\n    }\n\n    /// @dev Gets the current gas data from the gas oracle to be saved as part of the Origin State.\n    function _fetchGasData() internal view override returns (GasData) {\n        return GasDataLib.wrapGasData(InterfaceGasOracle(gasOracle).getGasData());\n    }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"158064:7264:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;158064:7264:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"158064:7264:0:-:0;;;;;;;;","abiDefinition":[],"userDoc":{"kind":"user","methods":{},"notice":"MerkleTree is work based on Nomad's Merkle.sol, which is used under MIT OR Apache-2.0 [link](https://github.com/nomad-xyz/monorepo/blob/main/packages/contracts-core/contracts/libs/Merkle.sol). With the following changes: - Adapted for Solidity 0.8.x. - Amount of tree leaves stored externally. - Added thorough documentation. - `H(0,0) = 0` optimization from [ER forum post](https://ethresear.ch/t/optimizing-sparse-merkle-trees/3751/6). \u003e Nomad's Merkle.sol is work based on eth2 deposit contract, which is used under CC0-1.0 [link](https://github.com/ethereum/deposit_contract/blob/dev/deposit_contract/contracts/validator_registration.v.py). With the following changes: \u003e - Implemented in Solidity 0.7.6 (eth2 deposit contract implemented in Vyper). \u003e - `H() = keccak256()` is used as the hashing function instead of `sha256()`.","version":1},"developerDoc":{"kind":"dev","methods":{},"stateVariables":{"MAX_LEAVES":{"details":"For root calculation we need at least one empty leaf, thus the minus one in the formula."}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"stateVariables\":{\"MAX_LEAVES\":{\"details\":\"For root calculation we need at least one empty leaf, thus the minus one in the formula.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"MerkleTree is work based on Nomad's Merkle.sol, which is used under MIT OR Apache-2.0 [link](https://github.com/nomad-xyz/monorepo/blob/main/packages/contracts-core/contracts/libs/Merkle.sol). With the following changes: - Adapted for Solidity 0.8.x. - Amount of tree leaves stored externally. - Added thorough documentation. - `H(0,0) = 0` optimization from [ER forum post](https://ethresear.ch/t/optimizing-sparse-merkle-trees/3751/6). \u003e Nomad's Merkle.sol is work based on eth2 deposit contract, which is used under CC0-1.0 [link](https://github.com/ethereum/deposit_contract/blob/dev/deposit_contract/contracts/validator_registration.v.py). With the following changes: \u003e - Implemented in Solidity 0.7.6 (eth2 deposit contract implemented in Vyper). \u003e - `H() = keccak256()` is used as the hashing function instead of `sha256()`.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Origin.sol\":\"MerkleTree\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Origin.sol\":{\"keccak256\":\"0x96775924f147f3d1f8df8cdf56731fe52a15af8d8e12e608efb8158c112b18cd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e642a27f5fab3c62b4c02e9754e9e42b1cf2e5381dbea9d3d106d23b7772ebe6\",\"dweb:/ipfs/QmUwn7ZyBvPkjnMuK8ZMSexBUdNQnVtxwyoAyT4DXLQjra\"]}},\"version\":1}"},"hashes":{}},"solidity/Origin.sol:MessageLib":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122037f54ffef1c7a1a484668df5610663e1a180793c62430cdeb08229a733a3e3b264736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122037f54ffef1c7a1a484668df5610663e1a180793c62430cdeb08229a733a3e3b264736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/OriginEvents.sol\n\n/// @notice A collection of events emitted by the Origin contract\nabstract contract OriginEvents {\n    /**\n     * @notice Emitted when a new message is sent.\n     * @param messageHash   Hash of message; the leaf inserted to the Merkle tree for the message\n     * @param nonce         Nonce of sent message (starts from 1)\n     * @param destination   Destination domain\n     * @param message       Raw bytes of message\n     */\n    event Sent(bytes32 indexed messageHash, uint32 indexed nonce, uint32 indexed destination, bytes message);\n\n    /**\n     * @notice Emitted when a tip withdrawal is completed.\n     * @param actor     Actor address\n     * @param tip       Tip value, denominated in local domain's wei\n     */\n    event TipWithdrawalCompleted(address actor, uint256 tip);\n}\n\n// contracts/events/StateHubEvents.sol\n\n/// @notice A collection of events emitted by the StateHub contract\nabstract contract StateHubEvents {\n    /**\n     * @notice Emitted when a new Origin State is saved after a message was sent.\n     * @param state     Raw payload with state data\n     */\n    event StateSaved(bytes state);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n    /**\n     * @notice Check that a given state is valid: matches the historical state of Origin contract.\n     * Note: any Agent including an invalid state in their snapshot will be slashed\n     * upon providing the snapshot and agent signature for it to Origin contract.\n     * @dev Will revert if any of these is true:\n     *  - State payload is not properly formatted.\n     * @param statePayload      Raw payload with state data\n     * @return isValid          Whether the provided state is valid\n     */\n    function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns the amount of saved states so far.\n     * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n     */\n    function statesAmount() external view returns (uint256);\n\n    /**\n     * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @return statePayload     Raw payload with the latest state data\n     */\n    function suggestLatestState() external view returns (bytes memory statePayload);\n\n    /**\n     * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @param nonce             Historical nonce to form a state\n     * @return statePayload     Raw payload with historical state data\n     */\n    function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/InterfaceGasOracle.sol\n\ninterface InterfaceGasOracle {\n    /**\n     * @notice Fetches the latest gas data for the chain from `Destination` contract,\n     * and uses it to update the oracle values for the requested chain.\n     * @param domain    Domain to update the gas data for\n     */\n    function updateGasData(uint32 domain) external;\n\n    /**\n     * @notice Returns the gas data for the local chain.\n     */\n    function getGasData() external view returns (uint256 paddedGasData);\n\n    /**\n     * @notice Returns the gas data for the given domain, in the decoded format.\n     * @param domain        Domain of chain to get gas data for\n     * @return gasPrice     Gas price for the chain (in Wei per gas unit)\n     * @return dataPrice    Calldata price (in Wei per byte of content)\n     * @return execBuffer   Tx fee safety buffer for message execution (in Wei)\n     * @return amortAttCost Amortized cost for attestation submission (in Wei)\n     * @return etherPrice   Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n     * @return markup       Markup for the message execution (in BWAD)\n     */\n    function getDecodedGasData(uint32 domain)\n        external\n        view\n        returns (\n            uint256 gasPrice,\n            uint256 dataPrice,\n            uint256 execBuffer,\n            uint256 amortAttCost,\n            uint256 etherPrice,\n            uint256 markup\n        );\n\n    /**\n     * @notice Returns the minimum tips for sending a message to a given destination.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return paddedTips       Padded encoded minimum tips information\n     */\n    function getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 paddedTips);\n}\n\n// contracts/interfaces/InterfaceOrigin.sol\n\ninterface InterfaceOrigin {\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /**\n     * @notice Send a message to the recipient located on destination domain.\n     * @dev Recipient has to conform to IMessageRecipient interface, otherwise message won't be delivered.\n     * Will revert if any of these is true:\n     * - `destination` is equal to contract's local domain\n     * - `content` length is greater than `MAX_CONTENT_BYTES`\n     * - `msg.value` is lower than value of minimum tips for the given message\n     * @param destination           Domain of destination chain\n     * @param recipient             Address of recipient on destination chain as bytes32\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param paddedRequest         Padded encoded message execution request on destination chain\n     * @param content               Raw bytes content of message\n     * @return messageNonce         Nonce of the sent message\n     * @return messageHash          Hash of the sent message\n     */\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable returns (uint32 messageNonce, bytes32 messageHash);\n\n    /**\n     * @notice Send a manager message to the destination domain.\n     * @dev This could only be called by AgentManager, which takes care of encoding the calldata payload.\n     * Note: (msgOrigin, proofMaturity) security args will be added to payload on the destination chain\n     * so that the AgentManager could verify where the Manager Message came from and how mature is the proof.\n     * Note: function is not payable, as no tips are required for sending a manager message.\n     * Will revert if `destination` is equal to contract's local domain.\n     * @param destination           Domain of destination chain\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param payload               Payload for calling AgentManager on destination chain (with extra security args)\n     */\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        returns (uint32 messageNonce, bytes32 messageHash);\n\n    // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Withdraws locked base message tips to the recipient.\n     * @dev Could only be called by a local AgentManager.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function withdrawTips(address recipient, uint256 amount) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the minimum tips value for sending a message to a given destination.\n     * @dev Using at least `tipsValue` as `msg.value` for `sendBaseMessage()`\n     * will guarantee that the message will be accepted.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return tipsValue        Minimum tips value for a message to be accepted\n     */\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue);\n}\n\n// contracts/libs/Constants.sol\n\n// Here we define common constants to enable their easier reusing later.\n\n// ══════════════════════════════════ MERKLE ═══════════════════════════════════\n/// @dev Height of the Agent Merkle Tree\nuint256 constant AGENT_TREE_HEIGHT = 32;\n/// @dev Height of the Origin Merkle Tree\nuint256 constant ORIGIN_TREE_HEIGHT = 32;\n/// @dev Height of the Snapshot Merkle Tree. Allows up to 64 leafs, e.g. up to 32 states\nuint256 constant SNAPSHOT_TREE_HEIGHT = 6;\n// ══════════════════════════════════ STRUCTS ══════════════════════════════════\n/// @dev See Attestation.sol: (bytes32,bytes32,uint32,uint40,uint40): 32+32+4+5+5\nuint256 constant ATTESTATION_LENGTH = 78;\n/// @dev See GasData.sol: (uint16,uint16,uint16,uint16,uint16,uint16): 2+2+2+2+2+2\nuint256 constant GAS_DATA_LENGTH = 12;\n/// @dev See Receipt.sol: (uint32,uint32,bytes32,bytes32,uint8,address,address,address): 4+4+32+32+1+20+20+20\nuint256 constant RECEIPT_LENGTH = 133;\n/// @dev See State.sol: (bytes32,uint32,uint32,uint40,uint40,GasData): 32+4+4+5+5+len(GasData)\nuint256 constant STATE_LENGTH = 50 + GAS_DATA_LENGTH;\n/// @dev Maximum amount of states in a single snapshot. Each state produces two leafs in the tree\nuint256 constant SNAPSHOT_MAX_STATES = 1 \u003c\u003c (SNAPSHOT_TREE_HEIGHT - 1);\n// ══════════════════════════════════ MESSAGE ══════════════════════════════════\n/// @dev See Header.sol: (uint8,uint32,uint32,uint32,uint32): 1+4+4+4+4\nuint256 constant HEADER_LENGTH = 17;\n/// @dev See Request.sol: (uint96,uint64,uint32): 12+8+4\nuint256 constant REQUEST_LENGTH = 24;\n/// @dev See Tips.sol: (uint64,uint64,uint64,uint64): 8+8+8+8\nuint256 constant TIPS_LENGTH = 32;\n/// @dev The amount of discarded last bits when encoding tip values\nuint256 constant TIPS_GRANULARITY = 32;\n/// @dev Tip values could be only the multiples of TIPS_MULTIPLIER\nuint256 constant TIPS_MULTIPLIER = 1 \u003c\u003c TIPS_GRANULARITY;\n// ══════════════════════════════ STATEMENT SALTS ══════════════════════════════\n/// @dev Salts for signing various statements\nbytes32 constant ATTESTATION_VALID_SALT = keccak256(\"ATTESTATION_VALID_SALT\");\nbytes32 constant ATTESTATION_INVALID_SALT = keccak256(\"ATTESTATION_INVALID_SALT\");\nbytes32 constant RECEIPT_VALID_SALT = keccak256(\"RECEIPT_VALID_SALT\");\nbytes32 constant RECEIPT_INVALID_SALT = keccak256(\"RECEIPT_INVALID_SALT\");\nbytes32 constant SNAPSHOT_VALID_SALT = keccak256(\"SNAPSHOT_VALID_SALT\");\nbytes32 constant STATE_INVALID_SALT = keccak256(\"STATE_INVALID_SALT\");\n// ═════════════════════════════════ PROTOCOL ══════════════════════════════════\n/// @dev Optimistic period for new agent roots in LightManager\nuint32 constant AGENT_ROOT_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Timeout between the agent root could be proposed and resolved in LightManager\nuint32 constant AGENT_ROOT_PROPOSAL_TIMEOUT = 12 hours;\nuint32 constant BONDING_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Amount of time that the Notary will not be considered active after they won a dispute\nuint32 constant DISPUTE_TIMEOUT_NOTARY = 12 hours;\n/// @dev Amount of time without fresh data from Notaries before contract owner can resolve stuck disputes manually\nuint256 constant FRESH_DATA_TIMEOUT = 4 hours;\n/// @dev Maximum bytes per message = 2 KiB (somewhat arbitrarily set to begin)\nuint256 constant MAX_CONTENT_BYTES = 2 * 2 ** 10;\n/// @dev Maximum value for the summit tip that could be set in GasOracle\nuint256 constant MAX_SUMMIT_TIP = 0.01 ether;\n\n// contracts/libs/Errors.sol\n\n// ══════════════════════════════ INVALID CALLER ═══════════════════════════════\n\nerror CallerNotAgentManager();\nerror CallerNotDestination();\nerror CallerNotInbox();\nerror CallerNotSummit();\n\n// ══════════════════════════════ INCORRECT DATA ═══════════════════════════════\n\nerror IncorrectAttestation();\nerror IncorrectAgentDomain();\nerror IncorrectAgentIndex();\nerror IncorrectAgentProof();\nerror IncorrectAgentRoot();\nerror IncorrectDataHash();\nerror IncorrectDestinationDomain();\nerror IncorrectOriginDomain();\nerror IncorrectSnapshotProof();\nerror IncorrectSnapshotRoot();\nerror IncorrectState();\nerror IncorrectStatesAmount();\nerror IncorrectTipsProof();\nerror IncorrectVersionLength();\n\nerror IncorrectNonce();\nerror IncorrectSender();\nerror IncorrectRecipient();\n\nerror FlagOutOfRange();\nerror IndexOutOfRange();\nerror NonceOutOfRange();\n\nerror OutdatedNonce();\n\nerror UnformattedAttestation();\nerror UnformattedAttestationReport();\nerror UnformattedBaseMessage();\nerror UnformattedCallData();\nerror UnformattedCallDataPrefix();\nerror UnformattedMessage();\nerror UnformattedReceipt();\nerror UnformattedReceiptReport();\nerror UnformattedSignature();\nerror UnformattedSnapshot();\nerror UnformattedState();\nerror UnformattedStateReport();\n\n// ═══════════════════════════════ MERKLE TREES ════════════════════════════════\n\nerror LeafNotProven();\nerror MerkleTreeFull();\nerror NotEnoughLeafs();\nerror TreeHeightTooLow();\n\n// ═════════════════════════════ OPTIMISTIC PERIOD ═════════════════════════════\n\nerror BaseClientOptimisticPeriod();\nerror MessageOptimisticPeriod();\nerror SlashAgentOptimisticPeriod();\nerror WithdrawTipsOptimisticPeriod();\nerror ZeroProofMaturity();\n\n// ═══════════════════════════════ AGENT MANAGER ═══════════════════════════════\n\nerror AgentNotGuard();\nerror AgentNotNotary();\n\nerror AgentCantBeAdded();\nerror AgentNotActive();\nerror AgentNotActiveNorUnstaking();\nerror AgentNotFraudulent();\nerror AgentNotUnstaking();\nerror AgentUnknown();\n\nerror AgentRootNotProposed();\nerror AgentRootTimeoutNotOver();\n\nerror NotStuck();\n\nerror DisputeAlreadyResolved();\nerror DisputeNotOpened();\nerror DisputeTimeoutNotOver();\nerror GuardInDispute();\nerror NotaryInDispute();\n\nerror MustBeSynapseDomain();\nerror SynapseDomainForbidden();\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\nerror AlreadyExecuted();\nerror AlreadyFailed();\nerror DuplicatedSnapshotRoot();\nerror IncorrectMagicValue();\nerror GasLimitTooLow();\nerror GasSuppliedTooLow();\n\n// ══════════════════════════════════ ORIGIN ═══════════════════════════════════\n\nerror ContentLengthTooBig();\nerror EthTransferFailed();\nerror InsufficientEthBalance();\n\n// ════════════════════════════════ GAS ORACLE ═════════════════════════════════\n\nerror LocalGasDataNotSet();\nerror RemoteGasDataNotSet();\n\n// ═══════════════════════════════════ TIPS ════════════════════════════════════\n\nerror SummitTipTooHigh();\nerror TipsClaimMoreThanEarned();\nerror TipsClaimZero();\nerror TipsOverflow();\nerror TipsValueTooLow();\n\n// ════════════════════════════════ MEMORY VIEW ════════════════════════════════\n\nerror IndexedTooMuch();\nerror ViewOverrun();\nerror OccupiedMemory();\nerror UnallocatedMemory();\nerror PrecompileOutOfGas();\n\n// ═════════════════════════════════ MULTICALL ═════════════════════════════════\n\nerror MulticallFailed();\n\n// contracts/libs/TypeCasts.sol\n\nlibrary TypeCasts {\n    // alignment preserving cast\n    function addressToBytes32(address addr) internal pure returns (bytes32) {\n        return bytes32(uint256(uint160(addr)));\n    }\n\n    // alignment preserving cast\n    function bytes32ToAddress(bytes32 buf) internal pure returns (address) {\n        return address(uint160(uint256(buf)));\n    }\n}\n\n// contracts/libs/stack/Number.sol\n\n/// Number is a compact representation of uint256, that is fit into 16 bits\n/// with the maximum relative error under 0.4%.\ntype Number is uint16;\n\nusing NumberLib for Number global;\n\n/// # Number\n/// Library for compact representation of uint256 numbers.\n/// - Number is stored using mantissa and exponent, each occupying 8 bits.\n/// - Numbers under 2**8 are stored as `mantissa` with `exponent = 0xFF`.\n/// - Numbers at least 2**8 are approximated as `(256 + mantissa) \u003c\u003c exponent`\n/// \u003e - `0 \u003c= mantissa \u003c 256`\n/// \u003e - `0 \u003c= exponent \u003c= 247` (`256 * 2**248` doesn't fit into uint256)\n/// # Number stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type  | Bytes |\n/// | ---------- | -------- | ----- | ----- |\n/// | (002..001] | mantissa | uint8 | 1     |\n/// | (001..000] | exponent | uint8 | 1     |\n\nlibrary NumberLib {\n    /// @dev Amount of bits to shift to mantissa field\n    uint16 private constant SHIFT_MANTISSA = 8;\n\n    /// @notice For bwad math (binary wad) we use 2**64 as \"wad\" unit.\n    /// @dev We are using not using 10**18 as wad, because it is not stored precisely in NumberLib.\n    uint256 internal constant BWAD_SHIFT = 64;\n    uint256 internal constant BWAD = 1 \u003c\u003c BWAD_SHIFT;\n    /// @notice ~0.1% in bwad units.\n    uint256 internal constant PER_MILLE_SHIFT = BWAD_SHIFT - 10;\n    uint256 internal constant PER_MILLE = 1 \u003c\u003c PER_MILLE_SHIFT;\n\n    /// @notice Compresses uint256 number into 16 bits.\n    function compress(uint256 value) internal pure returns (Number) {\n        // Find `msb` such as `2**msb \u003c= value \u003c 2**(msb + 1)`\n        uint256 msb = mostSignificantBit(value);\n        // We want to preserve 9 bits of precision.\n        // The highest bit is always 1, so we can skip it.\n        // The remaining 8 highest bits are stored as mantissa.\n        if (msb \u003c 8) {\n            // Value is less than 2**8, so we can use value as mantissa with \"-1\" exponent.\n            return _encode(uint8(value), 0xFF);\n        } else {\n            // We use `msb - 8` as exponent otherwise. Note that `exponent \u003e= 0`.\n            unchecked {\n                uint256 exponent = msb - 8;\n                // Shifting right by `msb-8` bits will shift the \"remaining 8 highest bits\" into the 8 lowest bits.\n                // uint8() will truncate the highest bit.\n                return _encode(uint8(value \u003e\u003e exponent), uint8(exponent));\n            }\n        }\n    }\n\n    /// @notice Decompresses 16 bits number into uint256.\n    /// @dev The outcome is an approximation of the original number: `(value - value / 256) \u003c number \u003c= value`.\n    function decompress(Number number) internal pure returns (uint256 value) {\n        // Isolate 8 highest bits as the mantissa.\n        uint256 mantissa = Number.unwrap(number) \u003e\u003e SHIFT_MANTISSA;\n        // This will truncate the highest bits, leaving only the exponent.\n        uint256 exponent = uint8(Number.unwrap(number));\n        if (exponent == 0xFF) {\n            return mantissa;\n        } else {\n            unchecked {\n                return (256 + mantissa) \u003c\u003c (exponent);\n            }\n        }\n    }\n\n    /// @dev Returns the most significant bit of `x`\n    /// https://solidity-by-example.org/bitwise/\n    function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\n        // To find `msb` we determine it bit by bit, starting from the highest one.\n        // `0 \u003c= msb \u003c= 255`, so we start from the highest bit, 1\u003c\u003c7 == 128.\n        // If `x` is at least 2**128, then the highest bit of `x` is at least 128.\n        // solhint-disable no-inline-assembly\n        assembly {\n            // `f` is set to 1\u003c\u003c7 if `x \u003e= 2**128` and to 0 otherwise.\n            let f := shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\n            // If `x \u003e= 2**128` then set `msb` highest bit to 1 and shift `x` right by 128.\n            // Otherwise, `msb` remains 0 and `x` remains unchanged.\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        // `x` is now at most 2**128 - 1. Continue the same way, the next highest bit is 1\u003c\u003c6 == 64.\n        assembly {\n            // `f` is set to 1\u003c\u003c6 if `x \u003e= 2**64` and to 0 otherwise.\n            let f := shl(6, gt(x, 0xFFFFFFFFFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c5 if `x \u003e= 2**32` and to 0 otherwise.\n            let f := shl(5, gt(x, 0xFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c4 if `x \u003e= 2**16` and to 0 otherwise.\n            let f := shl(4, gt(x, 0xFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c3 if `x \u003e= 2**8` and to 0 otherwise.\n            let f := shl(3, gt(x, 0xFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c2 if `x \u003e= 2**4` and to 0 otherwise.\n            let f := shl(2, gt(x, 0xF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c1 if `x \u003e= 2**2` and to 0 otherwise.\n            let f := shl(1, gt(x, 0x3))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1 if `x \u003e= 2**1` and to 0 otherwise.\n            let f := gt(x, 0x1)\n            msb := or(msb, f)\n        }\n    }\n\n    /// @dev Wraps (mantissa, exponent) pair into Number.\n    function _encode(uint8 mantissa, uint8 exponent) private pure returns (Number) {\n        // Casts below are upcasts, so they are safe.\n        return Number.wrap(uint16(mantissa) \u003c\u003c SHIFT_MANTISSA | uint16(exponent));\n    }\n}\n\n// contracts/libs/stack/Request.sol\n\n/// Request is encoded data with \"message execution request\".\ntype Request is uint192;\n\nusing RequestLib for Request global;\n\n/// Library for formatting _the request part_ of _the base messages_.\n/// - Request represents a message sender requirements for the message execution on the destination chain.\n/// - Request occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n/// \u003e gasDrop field is included for future compatibility and is ignored at the moment.\n///\n/// # Request stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type   | Bytes | Description                                          |\n/// | ---------- | -------- | ------ | ----- | ---------------------------------------------------- |\n/// | (024..012] | gasDrop  | uint96 | 12    | Minimum amount of gas token to drop to the recipient |\n/// | (012..004] | gasLimit | uint64 | 8     | Minimum amount of gas units to supply for execution  |\n/// | (004..000] | version  | uint32 | 4     | Base message version to pass to the recipient        |\n\nlibrary RequestLib {\n    /// @dev Amount of bits to shift to gasDrop field\n    uint192 private constant SHIFT_GAS_DROP = 12 * 8;\n    /// @dev Amount of bits to shift to gasLimit field\n    uint192 private constant SHIFT_GAS_LIMIT = 4 * 8;\n\n    /// @notice Returns an encoded request with the given fields\n    /// @param gasDrop_     Minimum amount of gas token to drop to the recipient (ignored at the moment)\n    /// @param gasLimit_    Minimum amount of gas units to supply for execution\n    /// @param version_     Base message version to pass to the recipient\n    function encodeRequest(uint96 gasDrop_, uint64 gasLimit_, uint32 version_) internal pure returns (Request) {\n        // Casts below are upcasts, so they are safe\n        return Request.wrap(uint192(gasDrop_) \u003c\u003c SHIFT_GAS_DROP | uint192(gasLimit_) \u003c\u003c SHIFT_GAS_LIMIT | version_);\n    }\n\n    /// @notice Wraps the padded encoded request into a Request-typed value.\n    /// @dev The \"padded\" request is simply an encoded request casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded requests\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedRequest) internal pure returns (Request) {\n        // Casting to uint192 will truncate the highest bits, which is the behavior we want\n        return Request.wrap(uint192(paddedRequest));\n    }\n\n    /// @notice Returns the requested of gas token to drop to the recipient.\n    function gasDrop(Request request) internal pure returns (uint96) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return uint96(Request.unwrap(request) \u003e\u003e SHIFT_GAS_DROP);\n    }\n\n    /// @notice Returns the requested minimum amount of gas units to supply for execution.\n    function gasLimit(Request request) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Request.unwrap(request) \u003e\u003e SHIFT_GAS_LIMIT);\n    }\n\n    /// @notice Returns the requested base message version to pass to the recipient.\n    function version(Request request) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Request.unwrap(request));\n    }\n}\n\n// node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        require(value \u003c= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        require(value \u003c= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        require(value \u003c= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value \u003c= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        require(value \u003c= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        require(value \u003c= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        require(value \u003c= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        require(value \u003c= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        require(value \u003c= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        require(value \u003c= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        require(value \u003c= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        require(value \u003c= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        require(value \u003c= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        require(value \u003c= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        require(value \u003c= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value \u003c= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        require(value \u003c= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        require(value \u003c= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        require(value \u003c= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value \u003c= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        require(value \u003c= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        require(value \u003c= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        require(value \u003c= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value \u003c= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        require(value \u003c= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        require(value \u003c= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        require(value \u003c= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value \u003c= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        require(value \u003c= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value \u003c= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value \u003c= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     *\n     * _Available since v3.0._\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value \u003e= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     *\n     * _Available since v3.0._\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value \u003c= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     *\n     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length \u003e 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance \u003e= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance \u003e= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length \u003e 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n\n// contracts/base/MultiCallable.sol\n\n/// @notice Collection of Multicall utilities. Fork of Multicall3:\n/// https://github.com/mds1/multicall/blob/master/src/Multicall3.sol\nabstract contract MultiCallable {\n    struct Call {\n        bool allowFailure;\n        bytes callData;\n    }\n\n    struct Result {\n        bool success;\n        bytes returnData;\n    }\n\n    /// @notice Aggregates a few calls to this contract into one multicall without modifying `msg.sender`.\n    function multicall(Call[] calldata calls) external returns (Result[] memory callResults) {\n        uint256 amount = calls.length;\n        callResults = new Result[](amount);\n        Call calldata call_;\n        for (uint256 i = 0; i \u003c amount;) {\n            call_ = calls[i];\n            Result memory result = callResults[i];\n            // We perform a delegate call to ourselves here. Delegate call does not modify `msg.sender`, so\n            // this will have the same effect as if `msg.sender` performed all the calls themselves one by one.\n            // solhint-disable-next-line avoid-low-level-calls\n            (result.success, result.returnData) = address(this).delegatecall(call_.callData);\n            // solhint-disable-next-line no-inline-assembly\n            assembly {\n                // Revert if the call fails and failure is not allowed\n                // `allowFailure := calldataload(call_)` and `success := mload(result)`\n                if iszero(or(calldataload(call_), mload(result))) {\n                    // Revert with `0x4d6a2328` (function selector for `MulticallFailed()`)\n                    mstore(0x00, 0x4d6a232800000000000000000000000000000000000000000000000000000000)\n                    revert(0x00, 0x04)\n                }\n            }\n            unchecked {\n                ++i;\n            }\n        }\n    }\n}\n\n// contracts/base/Version.sol\n\n/**\n * @title Versioned\n * @notice Version getter for contracts. Doesn't use any storage slots, meaning\n * it will never cause any troubles with the upgradeable contracts. For instance, this contract\n * can be added or removed from the inheritance chain without shifting the storage layout.\n */\nabstract contract Versioned {\n    /**\n     * @notice Struct that is mimicking the storage layout of a string with 32 bytes or less.\n     * Length is limited by 32, so the whole string payload takes two memory words:\n     * @param length    String length\n     * @param data      String characters\n     */\n    struct _ShortString {\n        uint256 length;\n        bytes32 data;\n    }\n\n    /// @dev Length of the \"version string\"\n    uint256 private immutable _length;\n    /// @dev Bytes representation of the \"version string\".\n    /// Strings with length over 32 are not supported!\n    bytes32 private immutable _data;\n\n    constructor(string memory version_) {\n        _length = bytes(version_).length;\n        if (_length \u003e 32) revert IncorrectVersionLength();\n        // bytes32 is left-aligned =\u003e this will store the byte representation of the string\n        // with the trailing zeroes to complete the 32-byte word\n        _data = bytes32(bytes(version_));\n    }\n\n    function version() external view returns (string memory versionString) {\n        // Load the immutable values to form the version string\n        _ShortString memory str = _ShortString(_length, _data);\n        // The only way to do this cast is doing some dirty assembly\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            versionString := str\n        }\n    }\n}\n\n// contracts/libs/ChainContext.sol\n\n/// @notice Library for accessing chain context variables as tightly packed integers.\n/// Messaging contracts should rely on this library for accessing chain context variables\n/// instead of doing the casting themselves.\nlibrary ChainContext {\n    using SafeCast for uint256;\n\n    /// @notice Returns the current block number as uint40.\n    /// @dev Reverts if block number is greater than 40 bits, which is not supposed to happen\n    /// until the block.timestamp overflows (assuming block time is at least 1 second).\n    function blockNumber() internal view returns (uint40) {\n        return block.number.toUint40();\n    }\n\n    /// @notice Returns the current block timestamp as uint40.\n    /// @dev Reverts if block timestamp is greater than 40 bits, which is\n    /// supposed to happen approximately in year 36835.\n    function blockTimestamp() internal view returns (uint40) {\n        return block.timestamp.toUint40();\n    }\n\n    /// @notice Returns the chain id as uint32.\n    /// @dev Reverts if chain id is greater than 32 bits, which is not\n    /// supposed to happen in production.\n    function chainId() internal view returns (uint32) {\n        return block.chainid.toUint32();\n    }\n}\n\n// contracts/libs/Structures.sol\n\n// Here we define common enums and structures to enable their easier reusing later.\n\n// ═══════════════════════════════ AGENT STATUS ════════════════════════════════\n\n/// @dev Potential statuses for the off-chain bonded agent:\n/// - Unknown: never provided a bond =\u003e signature not valid\n/// - Active: has a bond in BondingManager =\u003e signature valid\n/// - Unstaking: has a bond in BondingManager, initiated the unstaking =\u003e signature not valid\n/// - Resting: used to have a bond in BondingManager, successfully unstaked =\u003e signature not valid\n/// - Fraudulent: proven to commit fraud, value in Merkle Tree not updated =\u003e signature not valid\n/// - Slashed: proven to commit fraud, value in Merkle Tree was updated =\u003e signature not valid\n/// Unstaked agent could later be added back to THE SAME domain by staking a bond again.\n/// Honest agent: Unknown -\u003e Active -\u003e unstaking -\u003e Resting -\u003e Active ...\n/// Malicious agent: Unknown -\u003e Active -\u003e Fraudulent -\u003e Slashed\n/// Malicious agent: Unknown -\u003e Active -\u003e Unstaking -\u003e Fraudulent -\u003e Slashed\nenum AgentFlag {\n    Unknown,\n    Active,\n    Unstaking,\n    Resting,\n    Fraudulent,\n    Slashed\n}\n\n/// @notice Struct for storing an agent in the BondingManager contract.\nstruct AgentStatus {\n    AgentFlag flag;\n    uint32 domain;\n    uint32 index;\n}\n// 184 bits available for tight packing\n\nusing StructureUtils for AgentStatus global;\n\n/// @notice Potential statuses of an agent in terms of being in dispute\n/// - None: agent is not in dispute\n/// - Pending: agent is in unresolved dispute\n/// - Slashed: agent was in dispute that lead to agent being slashed\n/// Note: agent who won the dispute has their status reset to None\nenum DisputeFlag {\n    None,\n    Pending,\n    Slashed\n}\n\n/// @notice Struct for storing dispute status of an agent.\n/// @param flag         Dispute flag: None/Pending/Slashed.\n/// @param openedAt     Timestamp when the latest agent dispute was opened (zero if not opened).\n/// @param resolvedAt   Timestamp when the latest agent dispute was resolved (zero if not resolved).\nstruct DisputeStatus {\n    DisputeFlag flag;\n    uint40 openedAt;\n    uint40 resolvedAt;\n}\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\n/// @notice Struct representing the status of Destination contract.\n/// @param snapRootTime     Timestamp when latest snapshot root was accepted\n/// @param agentRootTime    Timestamp when latest agent root was accepted\n/// @param notaryIndex      Index of Notary who signed the latest agent root\nstruct DestinationStatus {\n    uint40 snapRootTime;\n    uint40 agentRootTime;\n    uint32 notaryIndex;\n}\n\n// ═══════════════════════════════ EXECUTION HUB ═══════════════════════════════\n\n/// @notice Potential statuses of the message in Execution Hub.\n/// - None: there hasn't been a valid attempt to execute the message yet\n/// - Failed: there was a valid attempt to execute the message, but recipient reverted\n/// - Success: there was a valid attempt to execute the message, and recipient did not revert\n/// Note: message can be executed until its status is Success\nenum MessageStatus {\n    None,\n    Failed,\n    Success\n}\n\nlibrary StructureUtils {\n    /// @notice Checks that Agent is Active\n    function verifyActive(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active) {\n            revert AgentNotActive();\n        }\n    }\n\n    /// @notice Checks that Agent is Unstaking\n    function verifyUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Unstaking) {\n            revert AgentNotUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Active or Unstaking\n    function verifyActiveUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active \u0026\u0026 status.flag != AgentFlag.Unstaking) {\n            revert AgentNotActiveNorUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Fraudulent\n    function verifyFraudulent(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Fraudulent) {\n            revert AgentNotFraudulent();\n        }\n    }\n\n    /// @notice Checks that Agent is not Unknown\n    function verifyKnown(AgentStatus memory status) internal pure {\n        if (status.flag == AgentFlag.Unknown) {\n            revert AgentUnknown();\n        }\n    }\n}\n\n// contracts/libs/memory/MemView.sol\n\n/// @dev MemView is an untyped view over a portion of memory to be used instead of `bytes memory`\ntype MemView is uint256;\n\n/// @dev Attach library functions to MemView\nusing MemViewLib for MemView global;\n\n/// @notice Library for operations with the memory views.\n/// Forked from https://github.com/summa-tx/memview-sol with several breaking changes:\n/// - The codebase is ported to Solidity 0.8\n/// - Custom errors are added\n/// - The runtime type checking is replaced with compile-time check provided by User-Defined Value Types\n///   https://docs.soliditylang.org/en/latest/types.html#user-defined-value-types\n/// - uint256 is used as the underlying type for the \"memory view\" instead of bytes29.\n///   It is wrapped into MemView custom type in order not to be confused with actual integers.\n/// - Therefore the \"type\" field is discarded, allowing to allocate 16 bytes for both view location and length\n/// - The documentation is expanded\n/// - Library functions unused by the rest of the codebase are removed\n//  - Very pretty code separators are added :)\nlibrary MemViewLib {\n    /// @notice Stack layout for uint256 (from highest bits to lowest)\n    /// (32 .. 16]      loc     16 bytes    Memory address of underlying bytes\n    /// (16 .. 00]      len     16 bytes    Length of underlying bytes\n\n    // ═══════════════════════════════════════════ BUILDING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Instantiate a new untyped memory view. This should generally not be called directly.\n     * Prefer `ref` wherever possible.\n     * @param loc_          The memory address\n     * @param len_          The length\n     * @return The new view with the specified location and length\n     */\n    function build(uint256 loc_, uint256 len_) internal pure returns (MemView) {\n        uint256 end_ = loc_ + len_;\n        // Make sure that a view is not constructed that points to unallocated memory\n        // as this could be indicative of a buffer overflow attack\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            if gt(end_, mload(0x40)) { end_ := 0 }\n        }\n        if (end_ == 0) {\n            revert UnallocatedMemory();\n        }\n        return _unsafeBuildUnchecked(loc_, len_);\n    }\n\n    /**\n     * @notice Instantiate a memory view from a byte array.\n     * @dev Note that due to Solidity memory representation, it is not possible to\n     * implement a deref, as the `bytes` type stores its len in memory.\n     * @param arr           The byte array\n     * @return The memory view over the provided byte array\n     */\n    function ref(bytes memory arr) internal pure returns (MemView) {\n        uint256 len_ = arr.length;\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 loc_;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // We add 0x20, so that the view starts exactly where the array data starts\n            loc_ := add(arr, 0x20)\n        }\n        return build(loc_, len_);\n    }\n\n    // ════════════════════════════════════════════ CLONING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to the new memory.\n     * @param memView       The memory view\n     * @return arr          The cloned byte array\n     */\n    function clone(MemView memView) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        unchecked {\n            _unsafeCopyTo(memView, ptr + 0x20);\n        }\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 len_ = memView.len();\n        uint256 footprint_ = memView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    /**\n     * @notice Copies all views, joins them into a new bytearray.\n     * @param memViews      The memory views\n     * @return arr          The new byte array with joined data behind the given views\n     */\n    function join(MemView[] memory memViews) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        MemView newView;\n        unchecked {\n            newView = _unsafeJoin(memViews, ptr + 0x20);\n        }\n        uint256 len_ = newView.len();\n        uint256 footprint_ = newView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    // ══════════════════════════════════════════ INSPECTING MEMORY VIEW ═══════════════════════════════════════════════\n\n    /**\n     * @notice Returns the memory address of the underlying bytes.\n     * @param memView       The memory view\n     * @return loc_         The memory address\n     */\n    function loc(MemView memView) internal pure returns (uint256 loc_) {\n        // loc is stored in the highest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u003e\u003e 128;\n    }\n\n    /**\n     * @notice Returns the number of bytes of the view.\n     * @param memView       The memory view\n     * @return len_         The length of the view\n     */\n    function len(MemView memView) internal pure returns (uint256 len_) {\n        // len is stored in the lowest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u0026 type(uint128).max;\n    }\n\n    /**\n     * @notice Returns the endpoint of `memView`.\n     * @param memView       The memory view\n     * @return end_         The endpoint of `memView`\n     */\n    function end(MemView memView) internal pure returns (uint256 end_) {\n        // The endpoint never overflows uint128, let alone uint256, so we could use unchecked math here\n        unchecked {\n            return memView.loc() + memView.len();\n        }\n    }\n\n    /**\n     * @notice Returns the number of memory words this memory view occupies, rounded up.\n     * @param memView       The memory view\n     * @return words_       The number of memory words\n     */\n    function words(MemView memView) internal pure returns (uint256 words_) {\n        // returning ceil(length / 32.0)\n        unchecked {\n            return (memView.len() + 31) \u003e\u003e 5;\n        }\n    }\n\n    /**\n     * @notice Returns the in-memory footprint of a fresh copy of the view.\n     * @param memView       The memory view\n     * @return footprint_   The in-memory footprint of a fresh copy of the view.\n     */\n    function footprint(MemView memView) internal pure returns (uint256 footprint_) {\n        // words() * 32\n        return memView.words() \u003c\u003c 5;\n    }\n\n    // ════════════════════════════════════════════ HASHING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the keccak256 hash of the underlying memory\n     * @param memView       The memory view\n     * @return digest       The keccak256 hash of the underlying memory\n     */\n    function keccak(MemView memView) internal pure returns (bytes32 digest) {\n        uint256 loc_ = memView.loc();\n        uint256 len_ = memView.len();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            digest := keccak256(loc_, len_)\n        }\n    }\n\n    /**\n     * @notice Adds a salt to the keccak256 hash of the underlying data and returns the keccak256 hash of the\n     * resulting data.\n     * @param memView       The memory view\n     * @return digestSalted keccak256(salt, keccak256(memView))\n     */\n    function keccakSalted(MemView memView, bytes32 salt) internal pure returns (bytes32 digestSalted) {\n        return keccak256(bytes.concat(salt, memView.keccak()));\n    }\n\n    // ════════════════════════════════════════════ SLICING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Safe slicing without memory modification.\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the given index\n     */\n    function slice(MemView memView, uint256 index_, uint256 len_) internal pure returns (MemView) {\n        uint256 loc_ = memView.loc();\n        // Ensure it doesn't overrun the view\n        if (loc_ + index_ + len_ \u003e memView.end()) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // loc_ + index_ \u003c= memView.end()\n            return build({loc_: loc_ + index_, len_: len_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing bytes from `index` to end(memView).\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @return The new view for the slice starting from the given index until the initial view endpoint\n     */\n    function sliceFrom(MemView memView, uint256 index_) internal pure returns (MemView) {\n        uint256 len_ = memView.len();\n        // Ensure it doesn't overrun the view\n        if (index_ \u003e len_) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // index_ \u003c= len_ =\u003e memView.loc() + index_ \u003c= memView.loc() + memView.len() == memView.end()\n            return build({loc_: memView.loc() + index_, len_: len_ - index_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the first `len` bytes.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the initial view beginning\n     */\n    function prefix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        return memView.slice({index_: 0, len_: len_});\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the last `len` byte.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length until the initial view endpoint\n     */\n    function postfix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        uint256 viewLen = memView.len();\n        // Ensure it doesn't overrun the view\n        if (len_ \u003e viewLen) {\n            revert ViewOverrun();\n        }\n        // Could do the unchecked math due to the check above\n        uint256 index_;\n        unchecked {\n            index_ = viewLen - len_;\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // len_ \u003c= memView.len() =\u003e memView.loc() \u003c= loc_ \u003c= memView.end()\n            return build({loc_: memView.loc() + viewLen - len_, len_: len_});\n        }\n    }\n\n    // ═══════════════════════════════════════════ INDEXING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Load up to 32 bytes from the view onto the stack.\n     * @dev Returns a bytes32 with only the `bytes_` HIGHEST bytes set.\n     * This can be immediately cast to a smaller fixed-length byte array.\n     * To automatically cast to an integer, use `indexUint`.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return result       The 32 byte result having only `bytes_` highest bytes set\n     */\n    function index(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (bytes32 result) {\n        if (bytes_ == 0) {\n            return bytes32(0);\n        }\n        // Can't load more than 32 bytes to the stack in one go\n        if (bytes_ \u003e 32) {\n            revert IndexedTooMuch();\n        }\n        // The last indexed byte should be within view boundaries\n        if (index_ + bytes_ \u003e memView.len()) {\n            revert ViewOverrun();\n        }\n        uint256 bitLength = bytes_ \u003c\u003c 3; // bytes_ * 8\n        uint256 loc_ = memView.loc();\n        // Get a mask with `bitLength` highest bits set\n        uint256 mask;\n        // 0x800...00 binary representation is 100...00\n        // sar stands for \"signed arithmetic shift\": https://en.wikipedia.org/wiki/Arithmetic_shift\n        // sar(N-1, 100...00) = 11...100..00, with exactly N highest bits set to 1\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            mask := sar(sub(bitLength, 1), 0x8000000000000000000000000000000000000000000000000000000000000000)\n        }\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load a full word using index offset, and apply mask to ignore non-relevant bytes\n            result := and(mload(add(loc_, index_)), mask)\n        }\n    }\n\n    /**\n     * @notice Parse an unsigned integer from the view at `index`.\n     * @dev Requires that the view have \u003e= `bytes_` bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return The unsigned integer\n     */\n    function indexUint(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (uint256) {\n        bytes32 indexedBytes = memView.index(index_, bytes_);\n        // `index()` returns left-aligned `bytes_`, while integers are right-aligned\n        // Shifting here to right-align with the full 32 bytes word: need to shift right `(32 - bytes_)` bytes\n        unchecked {\n            // memView.index() reverts when bytes_ \u003e 32, thus unchecked math\n            return uint256(indexedBytes) \u003e\u003e ((32 - bytes_) \u003c\u003c 3);\n        }\n    }\n\n    /**\n     * @notice Parse an address from the view at `index`.\n     * @dev Requires that the view have \u003e= 20 bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @return The address\n     */\n    function indexAddress(MemView memView, uint256 index_) internal pure returns (address) {\n        // index 20 bytes as `uint160`, and then cast to `address`\n        return address(uint160(memView.indexUint(index_, 20)));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns a memory view over the specified memory location\n    /// without checking if it points to unallocated memory.\n    function _unsafeBuildUnchecked(uint256 loc_, uint256 len_) private pure returns (MemView) {\n        // There is no scenario where loc or len would overflow uint128, so we omit this check.\n        // We use the highest 128 bits to encode the location and the lowest 128 bits to encode the length.\n        return MemView.wrap((loc_ \u003c\u003c 128) | len_);\n    }\n\n    /**\n     * @notice Copy the view to a location, return an unsafe memory reference\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memView       The memory view\n     * @param newLoc        The new location to copy the underlying view data\n     * @return The memory view over the unsafe memory with the copied underlying data\n     */\n    function _unsafeCopyTo(MemView memView, uint256 newLoc) private view returns (MemView) {\n        uint256 len_ = memView.len();\n        uint256 oldLoc = memView.loc();\n\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (newLoc \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        bool res;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // use the identity precompile (0x04) to copy\n            res := staticcall(gas(), 0x04, oldLoc, len_, newLoc, len_)\n        }\n        if (!res) revert PrecompileOutOfGas();\n        return _unsafeBuildUnchecked({loc_: newLoc, len_: len_});\n    }\n\n    /**\n     * @notice Join the views in memory, return an unsafe reference to the memory.\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memViews      The memory views\n     * @return The conjoined view pointing to the new memory\n     */\n    function _unsafeJoin(MemView[] memory memViews, uint256 location) private view returns (MemView) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (location \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        // Copy the views to the specified location one by one, by tracking the amount of copied bytes so far\n        uint256 offset = 0;\n        for (uint256 i = 0; i \u003c memViews.length;) {\n            MemView memView = memViews[i];\n            // We can use the unchecked math here as location + sum(view.length) will never overflow uint256\n            unchecked {\n                _unsafeCopyTo(memView, location + offset);\n                offset += memView.len();\n                ++i;\n            }\n        }\n        return _unsafeBuildUnchecked({loc_: location, len_: offset});\n    }\n}\n\n// contracts/libs/merkle/MerkleMath.sol\n\nlibrary MerkleMath {\n    // ═════════════════════════════════════════ BASIC MERKLE CALCULATIONS ═════════════════════════════════════════════\n\n    /**\n     * @notice Calculates the merkle root for the given leaf and merkle proof.\n     * @dev Will revert if proof length exceeds the tree height.\n     * @param index     Index of `leaf` in tree\n     * @param leaf      Leaf of the merkle tree\n     * @param proof     Proof of inclusion of `leaf` in the tree\n     * @param height    Height of the merkle tree\n     * @return root_    Calculated Merkle Root\n     */\n    function proofRoot(uint256 index, bytes32 leaf, bytes32[] memory proof, uint256 height)\n        internal\n        pure\n        returns (bytes32 root_)\n    {\n        // Proof length could not exceed the tree height\n        uint256 proofLen = proof.length;\n        if (proofLen \u003e height) revert TreeHeightTooLow();\n        root_ = leaf;\n        /// @dev Apply unchecked to all ++h operations\n        unchecked {\n            // Go up the tree levels from the leaf following the proof\n            for (uint256 h = 0; h \u003c proofLen; ++h) {\n                // Get a sibling node on current level: this is proof[h]\n                root_ = getParent(root_, proof[h], index, h);\n            }\n            // Go up to the root: the remaining siblings are EMPTY\n            for (uint256 h = proofLen; h \u003c height; ++h) {\n                root_ = getParent(root_, bytes32(0), index, h);\n            }\n        }\n    }\n\n    /**\n     * @notice Calculates the parent of a node on the path from one of the leafs to root.\n     * @param node          Node on a path from tree leaf to root\n     * @param sibling       Sibling for a given node\n     * @param leafIndex     Index of the tree leaf\n     * @param nodeHeight    \"Level height\" for `node` (ZERO for leafs, ORIGIN_TREE_HEIGHT for root)\n     */\n    function getParent(bytes32 node, bytes32 sibling, uint256 leafIndex, uint256 nodeHeight)\n        internal\n        pure\n        returns (bytes32 parent)\n    {\n        // Index for `node` on its \"tree level\" is (leafIndex / 2**height)\n        // \"Left child\" has even index, \"right child\" has odd index\n        if ((leafIndex \u003e\u003e nodeHeight) \u0026 1 == 0) {\n            // Left child\n            return getParent(node, sibling);\n        } else {\n            // Right child\n            return getParent(sibling, node);\n        }\n    }\n\n    /// @notice Calculates the parent of tow nodes in the merkle tree.\n    /// @dev We use implementation with H(0,0) = 0\n    /// This makes EVERY empty node in the tree equal to ZERO,\n    /// saving us from storing H(0,0), H(H(0,0), H(0, 0)), and so on\n    /// @param leftChild    Left child of the calculated node\n    /// @param rightChild   Right child of the calculated node\n    /// @return parent      Value for the node having above mentioned children\n    function getParent(bytes32 leftChild, bytes32 rightChild) internal pure returns (bytes32 parent) {\n        if (leftChild == bytes32(0) \u0026\u0026 rightChild == bytes32(0)) {\n            return 0;\n        } else {\n            return keccak256(bytes.concat(leftChild, rightChild));\n        }\n    }\n\n    // ════════════════════════════════ ROOT/PROOF CALCULATION FOR A LIST OF LEAFS ═════════════════════════════════════\n\n    /**\n     * @notice Calculates merkle root for a list of given leafs.\n     * Merkle Tree is constructed by padding the list with ZERO values for leafs until list length is `2**height`.\n     * Merkle Root is calculated for the constructed tree, and then saved in `leafs[0]`.\n     * \u003e Note:\n     * \u003e - `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * \u003e - Caller is expected not to reuse `hashes` list after the call, and only use `leafs[0]` value,\n     * which is guaranteed to contain the calculated merkle root.\n     * \u003e - root is calculated using the `H(0,0) = 0` Merkle Tree implementation. See MerkleTree.sol for details.\n     * @dev Amount of leaves should be at most `2**height`\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param height    Height of the Merkle Tree to construct\n     */\n    function calculateRoot(bytes32[] memory hashes, uint256 height) internal pure {\n        uint256 levelLength = hashes.length;\n        // Amount of hashes could not exceed amount of leafs in tree with the given height\n        if (levelLength \u003e (1 \u003c\u003c height)) revert TreeHeightTooLow();\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\": the amount of iterations for the for loop above.\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n            }\n        }\n    }\n\n    /**\n     * @notice Generates a proof of inclusion of a leaf in the list. If the requested index is outside\n     * of the list range, generates a proof of inclusion for an empty leaf (proof of non-inclusion).\n     * The Merkle Tree is constructed by padding the list with ZERO values until list length is a power of two\n     * __AND__ index is in the extended list range. For example:\n     *  - `hashes.length == 6` and `0 \u003c= index \u003c= 7` will \"extend\" the list to 8 entries.\n     *  - `hashes.length == 6` and `7 \u003c index \u003c= 15` will \"extend\" the list to 16 entries.\n     * \u003e Note: `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * Caller is expected not to reuse `hashes` list after the call.\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param index     Leaf index to generate the proof for\n     * @return proof    Generated merkle proof\n     */\n    function calculateProof(bytes32[] memory hashes, uint256 index) internal pure returns (bytes32[] memory proof) {\n        // Use only meaningful values for the shortened proof\n        // Check if index is within the list range (we want to generates proofs for outside leafs as well)\n        uint256 height = getHeight(index \u003c hashes.length ? hashes.length : (index + 1));\n        proof = new bytes32[](height);\n        uint256 levelLength = hashes.length;\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Use sibling for the merkle proof; `index^1` is index of our sibling\n                proof[h] = (index ^ 1 \u003c levelLength) ? hashes[index ^ 1] : bytes32(0);\n\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\"\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n                // Traverse to parent node\n                index \u003e\u003e= 1;\n            }\n        }\n    }\n\n    /// @notice Returns the height of the tree having a given amount of leafs.\n    function getHeight(uint256 leafs) internal pure returns (uint256 height) {\n        uint256 amount = 1;\n        while (amount \u003c leafs) {\n            unchecked {\n                ++height;\n            }\n            amount \u003c\u003c= 1;\n        }\n    }\n}\n\n// contracts/libs/stack/GasData.sol\n\n/// GasData in encoded data with \"basic information about gas prices\" for some chain.\ntype GasData is uint96;\n\nusing GasDataLib for GasData global;\n\n/// ChainGas is encoded data with given chain's \"basic information about gas prices\".\ntype ChainGas is uint128;\n\nusing GasDataLib for ChainGas global;\n\n/// Library for encoding and decoding GasData and ChainGas structs.\n/// # GasData\n/// `GasData` is a struct to store the \"basic information about gas prices\", that could\n/// be later used to approximate the cost of a message execution, and thus derive the\n/// minimal tip values for sending a message to the chain.\n/// \u003e - `GasData` is supposed to be cached by `GasOracle` contract, allowing to store the\n/// \u003e approximates instead of the exact values, and thus save on storage costs.\n/// \u003e - For instance, if `GasOracle` only updates the values on +- 10% change, having an\n/// \u003e 0.4% error on the approximates would be acceptable.\n/// `GasData` is supposed to be included in the Origin's state, which are synced across\n/// chains using Agent-signed snapshots and attestations.\n/// ## GasData stack layout (from highest bits to lowest)\n///\n/// | Position   | Field        | Type   | Bytes | Description                                         |\n/// | ---------- | ------------ | ------ | ----- | --------------------------------------------------- |\n/// | (012..010] | gasPrice     | uint16 | 2     | Gas price for the chain (in Wei per gas unit)       |\n/// | (010..008] | dataPrice    | uint16 | 2     | Calldata price (in Wei per byte of content)         |\n/// | (008..006] | execBuffer   | uint16 | 2     | Tx fee safety buffer for message execution (in Wei) |\n/// | (006..004] | amortAttCost | uint16 | 2     | Amortized cost for attestation submission (in Wei)  |\n/// | (004..002] | etherPrice   | uint16 | 2     | Chain's Ether Price / Mainnet Ether Price (in BWAD) |\n/// | (002..000] | markup       | uint16 | 2     | Markup for the message execution (in BWAD)          |\n/// \u003e See Number.sol for more details on `Number` type and BWAD (binary WAD) math.\n///\n/// ## ChainGas stack layout (from highest bits to lowest)\n///\n/// | Position   | Field   | Type   | Bytes | Description      |\n/// | ---------- | ------- | ------ | ----- | ---------------- |\n/// | (016..004] | gasData | uint96 | 12    | Chain's gas data |\n/// | (004..000] | domain  | uint32 | 4     | Chain's domain   |\nlibrary GasDataLib {\n    /// @dev Amount of bits to shift to gasPrice field\n    uint96 private constant SHIFT_GAS_PRICE = 10 * 8;\n    /// @dev Amount of bits to shift to dataPrice field\n    uint96 private constant SHIFT_DATA_PRICE = 8 * 8;\n    /// @dev Amount of bits to shift to execBuffer field\n    uint96 private constant SHIFT_EXEC_BUFFER = 6 * 8;\n    /// @dev Amount of bits to shift to amortAttCost field\n    uint96 private constant SHIFT_AMORT_ATT_COST = 4 * 8;\n    /// @dev Amount of bits to shift to etherPrice field\n    uint96 private constant SHIFT_ETHER_PRICE = 2 * 8;\n\n    /// @dev Amount of bits to shift to gasData field\n    uint128 private constant SHIFT_GAS_DATA = 4 * 8;\n\n    // ═════════════════════════════════════════════════ GAS DATA ══════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded GasData struct with the given fields.\n    /// @param gasPrice_        Gas price for the chain (in Wei per gas unit)\n    /// @param dataPrice_       Calldata price (in Wei per byte of content)\n    /// @param execBuffer_      Tx fee safety buffer for message execution (in Wei)\n    /// @param amortAttCost_    Amortized cost for attestation submission (in Wei)\n    /// @param etherPrice_      Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n    /// @param markup_          Markup for the message execution (in BWAD)\n    function encodeGasData(\n        Number gasPrice_,\n        Number dataPrice_,\n        Number execBuffer_,\n        Number amortAttCost_,\n        Number etherPrice_,\n        Number markup_\n    ) internal pure returns (GasData) {\n        // Number type wraps uint16, so could safely be casted to uint96\n        // forgefmt: disable-next-item\n        return GasData.wrap(\n            uint96(Number.unwrap(gasPrice_)) \u003c\u003c SHIFT_GAS_PRICE |\n            uint96(Number.unwrap(dataPrice_)) \u003c\u003c SHIFT_DATA_PRICE |\n            uint96(Number.unwrap(execBuffer_)) \u003c\u003c SHIFT_EXEC_BUFFER |\n            uint96(Number.unwrap(amortAttCost_)) \u003c\u003c SHIFT_AMORT_ATT_COST |\n            uint96(Number.unwrap(etherPrice_)) \u003c\u003c SHIFT_ETHER_PRICE |\n            uint96(Number.unwrap(markup_))\n        );\n    }\n\n    /// @notice Wraps padded uint256 value into GasData struct.\n    function wrapGasData(uint256 paddedGasData) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(paddedGasData));\n    }\n\n    /// @notice Returns the gas price, in Wei per gas unit.\n    function gasPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_GAS_PRICE));\n    }\n\n    /// @notice Returns the calldata price, in Wei per byte of content.\n    function dataPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_DATA_PRICE));\n    }\n\n    /// @notice Returns the tx fee safety buffer for message execution, in Wei.\n    function execBuffer(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_EXEC_BUFFER));\n    }\n\n    /// @notice Returns the amortized cost for attestation submission, in Wei.\n    function amortAttCost(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_AMORT_ATT_COST));\n    }\n\n    /// @notice Returns the ratio of Chain's Ether Price / Mainnet Ether Price, in BWAD math.\n    function etherPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_ETHER_PRICE));\n    }\n\n    /// @notice Returns the markup for the message execution, in BWAD math.\n    function markup(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data)));\n    }\n\n    // ════════════════════════════════════════════════ CHAIN DATA ═════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded ChainGas struct with the given fields.\n    /// @param gasData_ Chain's gas data\n    /// @param domain_  Chain's domain\n    function encodeChainGas(GasData gasData_, uint32 domain_) internal pure returns (ChainGas) {\n        // GasData type wraps uint96, so could safely be casted to uint128\n        return ChainGas.wrap(uint128(GasData.unwrap(gasData_)) \u003c\u003c SHIFT_GAS_DATA | uint128(domain_));\n    }\n\n    /// @notice Wraps padded uint256 value into ChainGas struct.\n    function wrapChainGas(uint256 paddedChainGas) internal pure returns (ChainGas) {\n        // Casting to uint128 will truncate the highest bits, which is the behavior we want\n        return ChainGas.wrap(uint128(paddedChainGas));\n    }\n\n    /// @notice Returns the chain's gas data.\n    function gasData(ChainGas data) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(ChainGas.unwrap(data) \u003e\u003e SHIFT_GAS_DATA));\n    }\n\n    /// @notice Returns the chain's domain.\n    function domain(ChainGas data) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(ChainGas.unwrap(data));\n    }\n\n    /// @notice Returns the hash for the list of ChainGas structs.\n    function snapGasHash(ChainGas[] memory snapGas) internal pure returns (bytes32 snapGasHash_) {\n        // Use assembly to calculate the hash of the array without copying it\n        // ChainGas takes a single word of storage, thus ChainGas[] is stored in the following way:\n        // 0x00: length of the array, in words\n        // 0x20: first ChainGas struct\n        // 0x40: second ChainGas struct\n        // And so on...\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Find the location where the array data starts, we add 0x20 to skip the length field\n            let loc := add(snapGas, 0x20)\n            // Load the length of the array (in words).\n            // Shifting left 5 bits is equivalent to multiplying by 32: this converts from words to bytes.\n            let len := shl(5, mload(snapGas))\n            // Calculate the hash of the array\n            snapGasHash_ := keccak256(loc, len)\n        }\n    }\n}\n\n// contracts/libs/stack/Header.sol\n\n/// Header is encoded data with \"general routing information\".\ntype Header is uint136;\n\nusing HeaderLib for Header global;\n\n/// Types of messages supported by Origin-Destination\n/// - Base: message sent by protocol user, contains tips\n/// - Manager: message sent between AgentManager contracts located on different chains, no tips\nenum MessageFlag {\n    Base,\n    Manager\n}\n\nusing HeaderLib for MessageFlag global;\n\n/// Library for formatting _the header part_ of _the messages used by Origin and Destination_.\n/// - Header represents general information for routing a Message for Origin and Destination.\n/// - Header occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n///\n/// # Header stack layout (from highest bits to lowest)\n///\n/// | Position   | Field            | Type   | Bytes | Description                             |\n/// | ---------- | ---------------- | ------ | ----- | --------------------------------------- |\n/// | (017..016] | flag             | uint8  | 1     | Flag specifying the type of message     |\n/// | (016..012] | origin           | uint32 | 4     | Domain where message originated         |\n/// | (012..008] | nonce            | uint32 | 4     | Message nonce on the origin domain      |\n/// | (008..004] | destination      | uint32 | 4     | Domain where message will be executed   |\n/// | (004..000] | optimisticPeriod | uint32 | 4     | Optimistic period that will be enforced |\nlibrary HeaderLib {\n    /// @dev Amount of bits to shift to flag field\n    uint136 private constant SHIFT_FLAG = 16 * 8;\n    /// @dev Amount of bits to shift to origin field\n    uint136 private constant SHIFT_ORIGIN = 12 * 8;\n    /// @dev Amount of bits to shift to nonce field\n    uint136 private constant SHIFT_NONCE = 8 * 8;\n    /// @dev Amount of bits to shift to destination field\n    uint136 private constant SHIFT_DESTINATION = 4 * 8;\n\n    /// @notice Returns an encoded header with provided fields\n    /// @param origin_              Domain of origin chain\n    /// @param nonce_               Message nonce on origin chain\n    /// @param destination_         Domain of destination chain\n    /// @param optimisticPeriod_    Optimistic period for message execution\n    function encodeHeader(\n        MessageFlag flag_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint32 destination_,\n        uint32 optimisticPeriod_\n    ) internal pure returns (Header) {\n        // All casts below are upcasts, so they are safe\n        // forgefmt: disable-next-item\n        return Header.wrap(\n            uint136(uint8(flag_)) \u003c\u003c SHIFT_FLAG |\n            uint136(origin_) \u003c\u003c SHIFT_ORIGIN |\n            uint136(nonce_) \u003c\u003c SHIFT_NONCE |\n            uint136(destination_) \u003c\u003c SHIFT_DESTINATION |\n            uint136(optimisticPeriod_)\n        );\n    }\n\n    /// @notice Checks that the header is a valid encoded header.\n    function isHeader(uint256 paddedHeader) internal pure returns (bool) {\n        // Check that flag is within range\n        return _flag(paddedHeader) \u003c= uint8(type(MessageFlag).max);\n    }\n\n    /// @notice Wraps the padded encoded request into a Header-typed value.\n    /// @dev The \"padded\" header is simply an encoded header casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded headers\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedHeader) internal pure returns (Header) {\n        // Check that flag is within range\n        if (!isHeader(paddedHeader)) revert FlagOutOfRange();\n        // Casting to uint136 will truncate the highest bits, which is the behavior we want\n        return Header.wrap(uint136(paddedHeader));\n    }\n\n    /// @notice Returns header's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Header header) internal pure returns (bytes32 hashedHeader) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store header in scratch space\n            mstore(0, header)\n            // Compute hash of header padded to 32 bytes\n            hashedHeader := keccak256(0, 32)\n        }\n    }\n\n    // ══════════════════════════════════════════════ HEADER SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns header's flag field\n    function flag(Header header) internal pure returns (MessageFlag) {\n        // We check that flag is within range when wrapping the header, so this cast is safe\n        return MessageFlag(_flag(Header.unwrap(header)));\n    }\n\n    /// @notice Returns header's origin field\n    function origin(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_ORIGIN);\n    }\n\n    /// @notice Returns header's nonce field\n    function nonce(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_NONCE);\n    }\n\n    /// @notice Returns header's destination field\n    function destination(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_DESTINATION);\n    }\n\n    /// @notice Returns header's optimistic seconds field\n    function optimisticPeriod(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns header's flag field without casting to MessageFlag\n    function _flag(uint256 paddedHeader) private pure returns (uint8) {\n        // Casting to uint8 will truncate the highest bits, which is the behavior we want\n        return uint8(paddedHeader \u003e\u003e SHIFT_FLAG);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n     * constructor.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall \u0026\u0026 _initialized \u003c 1) || (!AddressUpgradeable.isContract(address(this)) \u0026\u0026 _initialized == 1),\n            \"Initializable: contract is already initialized\"\n        );\n        _initialized = 1;\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: setting the version to 255 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing \u0026\u0026 _initialized \u003c version, \"Initializable: contract is already initialized\");\n        _initialized = version;\n        _initializing = true;\n        _;\n        _initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        require(_initializing, \"Initializable: contract is not initializing\");\n        _;\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized != type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint8) {\n        return _initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _initializing;\n    }\n}\n\n// contracts/interfaces/IAgentManager.sol\n\ninterface IAgentManager {\n    /**\n     * @notice Allows Inbox to open a Dispute between a Guard and a Notary, if they are both not in Dispute already.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Guard or Notary is already in Dispute.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Allows Inbox to slash an agent, if their fraud was proven.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Domain doesn't match the saved agent domain.\n     * @param domain    Domain where the Agent is active\n     * @param agent     Address of the Agent\n     * @param prover    Address that initially provided fraud proof\n     */\n    function slashAgent(uint32 domain, address agent, address prover) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest known root of the Agent Merkle Tree.\n     */\n    function agentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns the number of opened Disputes.\n     * @dev This includes the Disputes that have been resolved already.\n     */\n    function getDisputesAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns information about the dispute with the given index.\n     * @dev Will revert if dispute with given index hasn't been opened yet.\n     * @param index             Dispute index\n     * @return guard            Address of the Guard in the Dispute\n     * @return notary           Address of the Notary in the Dispute\n     * @return slashedAgent     Address of the Agent who was slashed when Dispute was resolved\n     * @return fraudProver      Address who provided fraud proof to resolve the Dispute\n     * @return reportPayload    Raw payload with report data that led to the Dispute\n     * @return reportSignature  Guard signature for the report payload\n     */\n    function getDispute(uint256 index)\n        external\n        view\n        returns (\n            address guard,\n            address notary,\n            address slashedAgent,\n            address fraudProver,\n            bytes memory reportPayload,\n            bytes memory reportSignature\n        );\n\n    /**\n     * @notice Returns the current Dispute status of a given agent. See Structures.sol for details.\n     * @dev Every returned value will be set to zero if agent was not slashed and is not in Dispute.\n     * `rival` and `disputePtr` will be set to zero if the agent was slashed without being in Dispute.\n     * @param agent         Agent address\n     * @return flag         Flag describing the current Dispute status for the agent: None/Pending/Slashed\n     * @return rival        Address of the rival agent in the Dispute\n     * @return fraudProver  Address who provided fraud proof to resolve the Dispute\n     * @return disputePtr   Index of the opened Dispute PLUS ONE. Zero if agent is not in Dispute.\n     */\n    function disputeStatus(address agent)\n        external\n        view\n        returns (DisputeFlag flag, address rival, address fraudProver, uint256 disputePtr);\n}\n\n// contracts/interfaces/IAgentSecured.sol\n\ninterface IAgentSecured {\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * between a Guard and a Notary has been opened.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * has been resolved due to one of the agents being slashed.\n     * \u003e `rivalIndex` will be ZERO, if the slashed agent was not in the Dispute.\n     * @param slashedIndex  Index of the slashed agent in the Agent Merkle Tree\n     * @param rivalIndex    Index of the their Dispute Rival in the Agent Merkle Tree\n     */\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the address of the local AgentManager contract, which is treated as\n     * the \"source of truth\" for agent statuses.\n     */\n    function agentManager() external view returns (address);\n\n    /**\n     * @notice Returns the address of the local Inbox contract, which is treated as\n     * the \"source of truth\" for agent-signed statements.\n     * @dev Inbox passes verified agent statements to `IAgentSecured` contract.\n     */\n    function inbox() external view returns (address);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns (flag, openedAt, resolvedAt) that describes the latest status of\n     * the latest dispute for an agent with a given index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param agentIndex    Agent index in the Agent Merkle Tree\n     * @return              Latest dispute status for the given agent: (flag, openedAt, resolvedAt)\n     */\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory);\n}\n\n// contracts/libs/memory/ByteString.sol\n\n/// @dev CallData is a memory view over the payload to be used for an external call, i.e.\n/// recipient.call(callData). Its length is always (4 + 32 * N) bytes:\n/// - First 4 bytes represent the function selector.\n/// - 32 * N bytes represent N words that function arguments occupy.\ntype CallData is uint256;\n\n/// @dev Attach library functions to CallData\nusing ByteString for CallData global;\n\n/// @dev Signature is a memory view over a \"65 bytes\" array representing a ECDSA signature.\ntype Signature is uint256;\n\n/// @dev Attach library functions to Signature\nusing ByteString for Signature global;\n\nlibrary ByteString {\n    using MemViewLib for bytes;\n\n    /**\n     * @dev non-compact ECDSA signatures are enforced as of OZ 4.7.3\n     *\n     *      Signature payload memory layout\n     * [000 .. 032) r   bytes32 32 bytes\n     * [032 .. 064) s   bytes32 32 bytes\n     * [064 .. 065) v   uint8    1 byte\n     */\n    uint256 internal constant SIGNATURE_LENGTH = 65;\n    uint256 private constant OFFSET_R = 0;\n    uint256 private constant OFFSET_S = 32;\n    uint256 private constant OFFSET_V = 64;\n\n    /**\n     * @dev Calldata memory layout\n     * [000 .. 004) selector    bytes4  4 bytes\n     *      Optional: N function arguments\n     * [004 .. 036) arg1        bytes32 32 bytes\n     *      ..\n     * [AAA .. END) argN        bytes32 32 bytes\n     */\n    uint256 internal constant SELECTOR_LENGTH = 4;\n    uint256 private constant OFFSET_SELECTOR = 0;\n    uint256 private constant OFFSET_ARGUMENTS = SELECTOR_LENGTH;\n\n    // ═════════════════════════════════════════════════ SIGNATURE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the signature payload from the given values.\n     * @dev Using ByteString.formatSignature({r: r, s: s, v: v}) will make sure\n     * that params are given in the right order.\n     */\n    function formatSignature(bytes32 r, bytes32 s, uint8 v) internal pure returns (bytes memory) {\n        return abi.encodePacked(r, s, v);\n    }\n\n    /**\n     * @notice Returns a Signature view over for the given payload.\n     * @dev Will revert if the payload is not a signature.\n     */\n    function castToSignature(bytes memory payload) internal pure returns (Signature) {\n        return castToSignature(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Signature view.\n     * @dev Will revert if the memory view is not over a signature.\n     */\n    function castToSignature(MemView memView) internal pure returns (Signature) {\n        if (!isSignature(memView)) revert UnformattedSignature();\n        return Signature.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a signature\n     */\n    function isSignature(MemView memView) internal pure returns (bool) {\n        return memView.len() == SIGNATURE_LENGTH;\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Signature signature) internal pure returns (MemView) {\n        return MemView.wrap(Signature.unwrap(signature));\n    }\n\n    // ═════════════════════════════════════════════ SIGNATURE SLICING ═════════════════════════════════════════════════\n\n    /// @notice Unpacks signature payload into (r, s, v) parameters.\n    /// @dev Make sure to verify signature length with isSignature() beforehand.\n    function toRSV(Signature signature) internal pure returns (bytes32 r, bytes32 s, uint8 v) {\n        // Get the underlying memory view\n        MemView memView = unwrap(signature);\n        r = memView.index({index_: OFFSET_R, bytes_: 32});\n        s = memView.index({index_: OFFSET_S, bytes_: 32});\n        // Can be safely casted to uint8, since we index a single byte\n        v = uint8(memView.indexUint({index_: OFFSET_V, bytes_: 1}));\n    }\n\n    // ═════════════════════════════════════════════════ CALLDATA ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the calldata with the modified arguments:\n     * the existing arguments are prepended with the arguments from the prefix.\n     * @dev Given:\n     *  - `calldata = abi.encodeWithSelector(foo.selector, d, e);`\n     *  - `prefix = abi.encode(a, b, c);`\n     *  - `a`, `b`, `c` are arguments of static type (i.e. not dynamically sized ones)\n     *      Then:\n     *  - Function will return abi.encodeWithSelector(foo.selector, a, c, c, d, e)\n     *  - Returned calldata will trigger `foo(a, b, c, d, e)` when used for a contract call.\n     * Note: for clarification as to what types are considered static, see\n     * https://docs.soliditylang.org/en/latest/abi-spec.html#formal-specification-of-the-encoding\n     * @param callData  Calldata that needs to be modified\n     * @param prefix    ABI-encoded arguments to use as the first arguments in the new calldata\n     * @return Modified calldata having prefix as the first arguments.\n     */\n    function addPrefix(CallData callData, bytes memory prefix) internal view returns (bytes memory) {\n        // Prefix should occupy a whole amount of words in memory\n        if (!_fullWords(prefix.length)) revert UnformattedCallDataPrefix();\n        MemView[] memory views = new MemView[](3);\n        // Use payload's function selector\n        views[0] = abi.encodePacked(callData.callSelector()).ref();\n        // Use prefix as the first arguments\n        views[1] = prefix.ref();\n        // Use payload's remaining arguments\n        views[2] = callData.arguments();\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a CallData view over for the given payload.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(bytes memory payload) internal pure returns (CallData) {\n        return castToCallData(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a CallData view.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(MemView memView) internal pure returns (CallData) {\n        if (!isCallData(memView)) revert UnformattedCallData();\n        return CallData.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a valid calldata, i.e.\n     * a function selector, followed by arbitrary amount of arguments.\n     */\n    function isCallData(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Calldata should at least have a function selector\n        if (length \u003c SELECTOR_LENGTH) return false;\n        // The remainder of the calldata should be exactly N memory words (N \u003e= 0)\n        return _fullWords(length - SELECTOR_LENGTH);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(CallData callData) internal pure returns (MemView) {\n        return MemView.wrap(CallData.unwrap(callData));\n    }\n\n    /// @notice Returns callData's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(CallData callData) internal pure returns (bytes32) {\n        return callData.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ CALLDATA SLICING ══════════════════════════════════════════════════\n\n    /**\n     * @notice Returns amount of memory words (32 byte chunks) the function arguments\n     * occupy in the calldata.\n     * @dev This might differ from amount of arguments supplied, if any of the arguments\n     * occupies more than one memory slot. It is true, however, that argument part of the payload\n     * occupies exactly N words, even for dynamic types like `bytes`\n     */\n    function argumentWords(CallData callData) internal pure returns (uint256) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        // Equivalent of (length - SELECTOR_LENGTH) / 32\n        return (memView.len() - SELECTOR_LENGTH) \u003e\u003e 5;\n    }\n\n    /// @notice Returns selector for the provided calldata.\n    function callSelector(CallData callData) internal pure returns (bytes4) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return bytes4(memView.index({index_: OFFSET_SELECTOR, bytes_: SELECTOR_LENGTH}));\n    }\n\n    /// @notice Returns abi encoded arguments for the provided calldata.\n    function arguments(CallData callData) internal pure returns (MemView) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return memView.sliceFrom({index_: OFFSET_ARGUMENTS});\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if length is full amount of memory words (32 bytes).\n    function _fullWords(uint256 length) internal pure returns (bool) {\n        // The equivalent of length % 32 == 0\n        return length \u0026 31 == 0;\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n    function __Context_init() internal onlyInitializing {\n    }\n\n    function __Context_init_unchained() internal onlyInitializing {\n    }\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[50] private __gap;\n}\n\n// contracts/libs/merkle/MerkleTree.sol\n\n/// `BaseTree` is a struct representing incremental merkle tree.\n/// - Contains only the current branch.\n/// - The number of inserted leaves is stored externally, and is later supplied for tree operations.\n/// - Has a fixed height of `ORIGIN_TREE_HEIGHT`.\n/// - Can store up to `2 ** ORIGIN_TREE_HEIGHT - 1` leaves.\n/// \u003e Note: the hash function for the tree `H(x, y)` is defined as:\n/// \u003e - `H(0,0) = 0`\n/// \u003e - `H(x,y) = keccak256(x, y), when (x != 0 || y != 0)`\n/// ## Invariant for leafs\n/// - The leftmost empty leaf has `index == count`, where `count` is the amount of the inserted leafs so far.\n/// - Value for any empty leaf or node is bytes32(0).\n/// ## Invariant for current branch\n/// `branch[i]` is always the value of a node on the i-th level.\n/// Levels are numbered from leafs to root: `0 .. ORIGIN_TREE_HEIGHT`.\n/// `branch[i]` stores the value for the node, such that:\n//  - The node is a \"left child\" (e.g. has an even index).\n/// - The node must have two non-empty children.\n/// - Out of all level's \"left child\" nodes with \"non-empty children\",\n/// the one with the biggest index (the rightmost one) is stored as `branch[i]`.\n/// \u003e __`branch` could be used to form a proof of inclusion for the first empty leaf (`index == count`).__\n/// _Here is how:_\n/// - Let's walk along the path from the \"first empty leaf\" to the root.\n/// - i-th bit of the \"first empty leaf\" index (which is equal to `count`) determines if the path's node\n/// for this i-th level is a \"left child\" or a \"right child\".\n/// - i-th bit in `count` is 0 → we are the left child on this level → sibling is the right child\n/// that does not exist yet → `proof[i] = bytes32(0)`.\n/// - i-th bit in `count` is 1 → we are the right child on this level → sibling is the left child\n/// sibling is the rightmost \"left child\" node on the level → `proof[i] = branch[i]`.\n/// \u003e Therefore `proof[i] = (count \u0026 (1 \u003c\u003c i)) == 0 ? bytes32(0) : branch[i])`\nstruct BaseTree {\n    bytes32[ORIGIN_TREE_HEIGHT] branch;\n}\n\nusing MerkleTree for BaseTree global;\n\n/// `HistoricalTree` is an incremental merkle tree keeping track of its historical merkle roots.\n/// \u003e - `roots[N]` is the root of the tree after `N` leafs were inserted\n/// \u003e - `roots[0] == bytes32(0)`\n/// @param tree     Incremental merkle tree\n/// @param roots    Historical merkle roots of the tree\nstruct HistoricalTree {\n    BaseTree tree;\n    bytes32[] roots;\n}\n\nusing MerkleTree for HistoricalTree global;\n\n/// `DynamicTree` is a struct representing a Merkle Tree with `2**AGENT_TREE_HEIGHT` leaves.\n/// - A single operation is available: update value for leaf with an arbitrary index (which might be a non-empty leaf).\n/// - This is done by requesting the proof of inclusion for the old value, which is used to both\n/// verify the old value, and calculate the new root.\n/// \u003e Based on Original idea from [ER forum post](https://ethresear.ch/t/efficient-on-chain-dynamic-merkle-tree/11054).\nstruct DynamicTree {\n    bytes32 root;\n}\n\nusing MerkleTree for DynamicTree global;\n\n/// MerkleTree is work based on Nomad's Merkle.sol, which is used under MIT OR Apache-2.0\n/// [link](https://github.com/nomad-xyz/monorepo/blob/main/packages/contracts-core/contracts/libs/Merkle.sol).\n/// With the following changes:\n/// - Adapted for Solidity 0.8.x.\n/// - Amount of tree leaves stored externally.\n/// - Added thorough documentation.\n/// - `H(0,0) = 0` optimization from [ER forum post](https://ethresear.ch/t/optimizing-sparse-merkle-trees/3751/6).\n/// \u003e Nomad's Merkle.sol is work based on eth2 deposit contract, which is used under CC0-1.0\n///[link](https://github.com/ethereum/deposit_contract/blob/dev/deposit_contract/contracts/validator_registration.v.py).\n/// With the following changes:\n/// \u003e - Implemented in Solidity 0.7.6 (eth2 deposit contract implemented in Vyper).\n/// \u003e - `H() = keccak256()` is used as the hashing function instead of `sha256()`.\nlibrary MerkleTree {\n    /// @dev For root calculation we need at least one empty leaf, thus the minus one in the formula.\n    uint256 internal constant MAX_LEAVES = 2 ** ORIGIN_TREE_HEIGHT - 1;\n\n    // ═════════════════════════════════════════════════ BASE TREE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Inserts `node` into merkle tree\n     * @dev Reverts if tree is full\n     * @param newCount  Amount of inserted leaves in the tree after the insertion (i.e. current + 1)\n     * @param node      Element to insert into tree\n     */\n    function insertBase(BaseTree storage tree, uint256 newCount, bytes32 node) internal {\n        if (newCount \u003e MAX_LEAVES) revert MerkleTreeFull();\n        // We go up the tree following the branch from the empty leaf AFTER the just inserted one.\n        // We stop when we find the first \"right child\" node.\n        // Its sibling is now the rightmost \"left child\" node that has two non-empty children.\n        // Therefore we need to update `tree.branch` value on this level.\n        // One could see that `tree.branch` value on lower and higher levels remain unchanged.\n\n        // Loop invariant: `node` is the current level's value for the branch from JUST INSERTED leaf\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            if ((newCount \u0026 1) == 1) {\n                // Found the first \"right child\" node on the branch from EMPTY leaf\n                // `node` is the value for node on branch from JUST INSERTED leaf\n                // Which in this case is the \"left child\".\n                // We update tree.branch and exit\n                tree.branch[i] = node;\n                return;\n            }\n            // On the branch from EMPTY leaf this is still a \"left child\".\n            // Meaning on branch from JUST INSERTED leaf, `node` is a right child.\n            // We compute value for `node` parent using `tree.branch` invariant:\n            // This is the rightmost \"left child\" node, which would be sibling of `node`.\n            node = MerkleMath.getParent(tree.branch[i], node);\n            // Get the parent index, and go to the next tree level\n            newCount \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n        // As the loop should always end prematurely with the `return` statement,\n        // this code should be unreachable. We assert `false` just to be safe.\n        assert(false);\n    }\n\n    /**\n     * @notice Calculates and returns current root of the merkle tree.\n     * @param count     Current amount of inserted leaves in the tree\n     * @return current  Calculated root of `tree`\n     */\n    function rootBase(BaseTree storage tree, uint256 count) internal view returns (bytes32 current) {\n        // To calculate the root we follow the branch of first EMPTY leaf (index == count)\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            // Check if we are the left or the right child on the current level\n            if ((count \u0026 1) == 1) {\n                // We are the right child. Our sibling is the \"rightmost\" \"left-child\" node\n                // that has two non-empty children → sibling is `tree.branch[i]`\n                current = MerkleMath.getParent(tree.branch[i], current);\n            } else {\n                // We are the left child. Our sibling does not exist yet → sibling is EMPTY\n                current = MerkleMath.getParent(current, bytes32(0));\n            }\n            // Get the parent index, and go to the next tree level\n            count \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    // ══════════════════════════════════════════════ HISTORICAL TREE ══════════════════════════════════════════════════\n\n    /// @notice Initializes the historical roots for the tree by inserting an empty root.\n    // solhint-disable-next-line ordering\n    function initializeRoots(HistoricalTree storage tree) internal returns (bytes32 savedRoot) {\n        // This should only be called once, when the contract is initialized\n        assert(tree.roots.length == 0);\n        // Save root for empty merkle tree: bytes32(0)\n        tree.roots.push(savedRoot);\n    }\n\n    /// @notice Inserts a new leaf into the merkle tree.\n    /// @dev Reverts if tree is full.\n    /// @param node         Element to insert into tree\n    /// @return newRoot     Merkle root after the leaf was inserted\n    function insert(HistoricalTree storage tree, bytes32 node) internal returns (bytes32 newRoot) {\n        // Tree count after the new leaf will be inserted (we store roots[0] as root of empty tree)\n        uint256 newCount = tree.roots.length;\n        tree.tree.insertBase(newCount, node);\n        // Save the new root\n        newRoot = tree.tree.rootBase(newCount);\n        tree.roots.push(newRoot);\n    }\n\n    /// @notice Returns the historical root of the merkle tree.\n    /// @dev Reverts if not enough leafs have been inserted.\n    /// @param count            Amount of leafs in the tree at some point of time\n    /// @return historicalRoot  Merkle root after `count` leafs were inserted\n    function root(HistoricalTree storage tree, uint256 count) internal view returns (bytes32 historicalRoot) {\n        if (count \u003e= tree.roots.length) revert NotEnoughLeafs();\n        return tree.roots[count];\n    }\n\n    // ═══════════════════════════════════════════════ DYNAMIC TREE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Updates the value for the leaf with the given index in the Dynamic Merkle Tree.\n     * @dev Will revert if incorrect proof of inclusion for old value is supplied.\n     * @param tree          Dynamic merkle tree\n     * @param index         Index of the leaf to update\n     * @param oldValue      Previous value of the leaf\n     * @param branch        Proof of inclusion of previous value into the tree\n     * @param newValue      New leaf value to assign\n     * @return newRoot      New value for the Merkle Root after the leaf is updated\n     */\n    function update(\n        DynamicTree storage tree,\n        uint256 index,\n        bytes32 oldValue,\n        bytes32[] memory branch,\n        bytes32 newValue\n    ) internal returns (bytes32 newRoot) {\n        // Check that the old value + proof result in a correct root\n        if (MerkleMath.proofRoot(index, oldValue, branch, AGENT_TREE_HEIGHT) != tree.root) {\n            revert LeafNotProven();\n        }\n        // New root is new value + the same proof (values for sibling nodes are not updated)\n        newRoot = MerkleMath.proofRoot(index, newValue, branch, AGENT_TREE_HEIGHT);\n        // Write the new root\n        tree.root = newRoot;\n    }\n}\n\n// contracts/libs/stack/Tips.sol\n\n/// Tips is encoded data with \"tips paid for sending a base message\".\n/// Note: even though uint256 is also an underlying type for MemView, Tips is stored ON STACK.\ntype Tips is uint256;\n\nusing TipsLib for Tips global;\n\n/// # Tips\n/// Library for formatting _the tips part_ of _the base messages_.\n///\n/// ## How the tips are awarded\n/// Tips are paid for sending a base message, and are split across all the agents that\n/// made the message execution on destination chain possible.\n/// ### Summit tips\n/// Split between:\n///     - Guard posting a snapshot with state ST_G for the origin chain.\n///     - Notary posting a snapshot SN_N using ST_G. This creates attestation A.\n///     - Notary posting a message receipt after it is executed on destination chain.\n/// ### Attestation tips\n/// Paid to:\n///     - Notary posting attestation A to destination chain.\n/// ### Execution tips\n/// Paid to:\n///     - First executor performing a valid execution attempt (correct proofs, optimistic period over),\n///      using attestation A to prove message inclusion on origin chain, whether the recipient reverted or not.\n/// ### Delivery tips.\n/// Paid to:\n///     - Executor who successfully executed the message on destination chain.\n///\n/// ## Tips encoding\n/// - Tips occupy a single storage word, and thus are stored on stack instead of being stored in memory.\n/// - The actual tip values should be determined by multiplying stored values by divided by TIPS_MULTIPLIER=2**32.\n/// - Tips are packed into a single word of storage, while allowing real values up to ~8*10**28 for every tip category.\n/// \u003e The only downside is that the \"real tip values\" are now multiplies of ~4*10**9, which should be fine even for\n/// the chains with the most expensive gas currency.\n/// # Tips stack layout (from highest bits to lowest)\n///\n/// | Position   | Field          | Type   | Bytes | Description                                                |\n/// | ---------- | -------------- | ------ | ----- | ---------------------------------------------------------- |\n/// | (032..024] | summitTip      | uint64 | 8     | Tip for agents interacting with Summit contract            |\n/// | (024..016] | attestationTip | uint64 | 8     | Tip for Notary posting attestation to Destination contract |\n/// | (016..008] | executionTip   | uint64 | 8     | Tip for valid execution attempt on destination chain       |\n/// | (008..000] | deliveryTip    | uint64 | 8     | Tip for successful message delivery on destination chain   |\n\nlibrary TipsLib {\n    using SafeCast for uint256;\n\n    /// @dev Amount of bits to shift to summitTip field\n    uint256 private constant SHIFT_SUMMIT_TIP = 24 * 8;\n    /// @dev Amount of bits to shift to attestationTip field\n    uint256 private constant SHIFT_ATTESTATION_TIP = 16 * 8;\n    /// @dev Amount of bits to shift to executionTip field\n    uint256 private constant SHIFT_EXECUTION_TIP = 8 * 8;\n\n    // ═══════════════════════════════════════════════════ TIPS ════════════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips with the given fields\n    /// @param summitTip_        Tip for agents interacting with Summit contract, divided by TIPS_MULTIPLIER\n    /// @param attestationTip_   Tip for Notary posting attestation to Destination contract, divided by TIPS_MULTIPLIER\n    /// @param executionTip_     Tip for valid execution attempt on destination chain, divided by TIPS_MULTIPLIER\n    /// @param deliveryTip_      Tip for successful message delivery on destination chain, divided by TIPS_MULTIPLIER\n    function encodeTips(uint64 summitTip_, uint64 attestationTip_, uint64 executionTip_, uint64 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // forgefmt: disable-next-item\n        return Tips.wrap(\n            uint256(summitTip_) \u003c\u003c SHIFT_SUMMIT_TIP |\n            uint256(attestationTip_) \u003c\u003c SHIFT_ATTESTATION_TIP |\n            uint256(executionTip_) \u003c\u003c SHIFT_EXECUTION_TIP |\n            uint256(deliveryTip_)\n        );\n    }\n\n    /// @notice Convenience function to encode tips with uint256 values.\n    function encodeTips256(uint256 summitTip_, uint256 attestationTip_, uint256 executionTip_, uint256 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // In practice, the tips amounts are not supposed to be higher than 2**96, and with 32 bits of granularity\n        // using uint64 is enough to store the values. However, we still check for overflow just in case.\n        // TODO: consider using Number type to store the tips values.\n        return encodeTips({\n            summitTip_: (summitTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            attestationTip_: (attestationTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            executionTip_: (executionTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            deliveryTip_: (deliveryTip_ \u003e\u003e TIPS_GRANULARITY).toUint64()\n        });\n    }\n\n    /// @notice Wraps the padded encoded tips into a Tips-typed value.\n    /// @dev There is no actual padding here, as the underlying type is already uint256,\n    /// but we include this function for consistency and to be future-proof, if tips will eventually use anything\n    /// smaller than uint256.\n    function wrapPadded(uint256 paddedTips) internal pure returns (Tips) {\n        return Tips.wrap(paddedTips);\n    }\n\n    /**\n     * @notice Returns a formatted Tips payload specifying empty tips.\n     * @return Formatted tips\n     */\n    function emptyTips() internal pure returns (Tips) {\n        return Tips.wrap(0);\n    }\n\n    /// @notice Returns tips's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Tips tips) internal pure returns (bytes32 hashedTips) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store tips in scratch space\n            mstore(0, tips)\n            // Compute hash of tips padded to 32 bytes\n            hashedTips := keccak256(0, 32)\n        }\n    }\n\n    // ═══════════════════════════════════════════════ TIPS SLICING ════════════════════════════════════════════════════\n\n    /// @notice Returns summitTip field\n    function summitTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_SUMMIT_TIP);\n    }\n\n    /// @notice Returns attestationTip field\n    function attestationTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_ATTESTATION_TIP);\n    }\n\n    /// @notice Returns executionTip field\n    function executionTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_EXECUTION_TIP);\n    }\n\n    /// @notice Returns deliveryTip field\n    function deliveryTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips));\n    }\n\n    // ════════════════════════════════════════════════ TIPS VALUE ═════════════════════════════════════════════════════\n\n    /// @notice Returns total value of the tips payload.\n    /// This is the sum of the encoded values, scaled up by TIPS_MULTIPLIER\n    function value(Tips tips) internal pure returns (uint256 value_) {\n        value_ = uint256(tips.summitTip()) + tips.attestationTip() + tips.executionTip() + tips.deliveryTip();\n        value_ \u003c\u003c= TIPS_GRANULARITY;\n    }\n\n    /// @notice Increases the delivery tip to match the new value.\n    function matchValue(Tips tips, uint256 newValue) internal pure returns (Tips newTips) {\n        uint256 oldValue = tips.value();\n        if (newValue \u003c oldValue) revert TipsValueTooLow();\n        // We want to increase the delivery tip, while keeping the other tips the same\n        unchecked {\n            uint256 delta = (newValue - oldValue) \u003e\u003e TIPS_GRANULARITY;\n            // `delta` fits into uint224, as TIPS_GRANULARITY is 32, so this never overflows uint256.\n            // In practice, this will never overflow uint64 as well, but we still check it just in case.\n            if (delta + tips.deliveryTip() \u003e type(uint64).max) revert TipsOverflow();\n            // Delivery tips occupy lowest 8 bytes, so we can just add delta to the tips value\n            // to effectively increase the delivery tip (knowing that delta fits into uint64).\n            newTips = Tips.wrap(Tips.unwrap(tips) + delta);\n        }\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    function __Ownable_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable_init_unchained() internal onlyInitializing {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n    function __Ownable2Step_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable2Step_init_unchained() internal onlyInitializing {\n    }\n    address private _pendingOwner;\n\n    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Returns the address of the pending owner.\n     */\n    function pendingOwner() public view virtual returns (address) {\n        return _pendingOwner;\n    }\n\n    /**\n     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual override onlyOwner {\n        _pendingOwner = newOwner;\n        emit OwnershipTransferStarted(owner(), newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual override {\n        delete _pendingOwner;\n        super._transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev The new owner accepts the ownership transfer.\n     */\n    function acceptOwnership() public virtual {\n        address sender = _msgSender();\n        require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n        _transferOwnership(sender);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// contracts/libs/memory/State.sol\n\n/// State is a memory view over a formatted state payload.\ntype State is uint256;\n\nusing StateLib for State global;\n\n/// # State\n/// State structure represents the state of Origin contract at some point of time.\n/// - State is structured in a way to track the updates of the Origin Merkle Tree.\n/// - State includes root of the Origin Merkle Tree, origin domain and some additional metadata.\n/// ## Origin Merkle Tree\n/// Hash of every sent message is inserted in the Origin Merkle Tree, which changes\n/// the value of Origin Merkle Root (which is the root for the mentioned tree).\n/// - Origin has a single Merkle Tree for all messages, regardless of their destination domain.\n/// - This leads to Origin state being updated if and only if a message was sent in a block.\n/// - Origin contract is a \"source of truth\" for states: a state is considered \"valid\" in its Origin,\n/// if it matches the state of the Origin contract after the N-th (nonce) message was sent.\n///\n/// # Memory layout of State fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                    |\n/// | ---------- | ----------- | ------- | ----- | ------------------------------ |\n/// | [000..032) | root        | bytes32 | 32    | Root of the Origin Merkle Tree |\n/// | [032..036) | origin      | uint32  | 4     | Domain where Origin is located |\n/// | [036..040) | nonce       | uint32  | 4     | Amount of sent messages        |\n/// | [040..045) | blockNumber | uint40  | 5     | Block of last sent message     |\n/// | [045..050) | timestamp   | uint40  | 5     | Time of last sent message      |\n/// | [050..062) | gasData     | uint96  | 12    | Gas data for the chain         |\n///\n/// @dev State could be used to form a Snapshot to be signed by a Guard or a Notary.\nlibrary StateLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_ROOT = 0;\n    uint256 private constant OFFSET_ORIGIN = 32;\n    uint256 private constant OFFSET_NONCE = 36;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 40;\n    uint256 private constant OFFSET_TIMESTAMP = 45;\n    uint256 private constant OFFSET_GAS_DATA = 50;\n\n    // ═══════════════════════════════════════════════════ STATE ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted State payload with provided fields\n     * @param root_         New merkle root\n     * @param origin_       Domain of Origin's chain\n     * @param nonce_        Nonce of the merkle root\n     * @param blockNumber_  Block number when root was saved in Origin\n     * @param timestamp_    Block timestamp when root was saved in Origin\n     * @param gasData_      Gas data for the chain\n     * @return Formatted state\n     */\n    function formatState(\n        bytes32 root_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_,\n        GasData gasData_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(root_, origin_, nonce_, blockNumber_, timestamp_, gasData_);\n    }\n\n    /**\n     * @notice Returns a State view over the given payload.\n     * @dev Will revert if the payload is not a state.\n     */\n    function castToState(bytes memory payload) internal pure returns (State) {\n        return castToState(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a State view.\n     * @dev Will revert if the memory view is not over a state.\n     */\n    function castToState(MemView memView) internal pure returns (State) {\n        if (!isState(memView)) revert UnformattedState();\n        return State.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted State.\n    function isState(MemView memView) internal pure returns (bool) {\n        return memView.len() == STATE_LENGTH;\n    }\n\n    /// @notice Returns the hash of a State, that could be later signed by a Guard to signal\n    /// that the state is invalid.\n    function hashInvalid(State state) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(stateInvalidSalt, keccak(state))\n        return state.unwrap().keccakSalted(STATE_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(State state) internal pure returns (MemView) {\n        return MemView.wrap(State.unwrap(state));\n    }\n\n    /// @notice Compares two State structures.\n    function equals(State a, State b) internal pure returns (bool) {\n        // Length of a State payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═══════════════════════════════════════════════ STATE HASHING ═══════════════════════════════════════════════════\n\n    /// @notice Returns the hash of the State.\n    /// @dev We are using the Merkle Root of a tree with two leafs (see below) as state hash.\n    function leaf(State state) internal pure returns (bytes32) {\n        (bytes32 leftLeaf_, bytes32 rightLeaf_) = state.subLeafs();\n        // Final hash is the parent of these leafs\n        return keccak256(bytes.concat(leftLeaf_, rightLeaf_));\n    }\n\n    /// @notice Returns \"sub-leafs\" of the State. Hash of these \"sub leafs\" is going to be used\n    /// as a \"state leaf\" in the \"Snapshot Merkle Tree\".\n    /// This enables proving that leftLeaf = (root, origin) was a part of the \"Snapshot Merkle Tree\",\n    /// by combining `rightLeaf` with the remainder of the \"Snapshot Merkle Proof\".\n    function subLeafs(State state) internal pure returns (bytes32 leftLeaf_, bytes32 rightLeaf_) {\n        MemView memView = state.unwrap();\n        // Left leaf is (root, origin)\n        leftLeaf_ = memView.prefix({len_: OFFSET_NONCE}).keccak();\n        // Right leaf is (metadata), or (nonce, blockNumber, timestamp)\n        rightLeaf_ = memView.sliceFrom({index_: OFFSET_NONCE}).keccak();\n    }\n\n    /// @notice Returns the left \"sub-leaf\" of the State.\n    function leftLeaf(bytes32 root_, uint32 origin_) internal pure returns (bytes32) {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(root_, origin_));\n    }\n\n    /// @notice Returns the right \"sub-leaf\" of the State.\n    function rightLeaf(uint32 nonce_, uint40 blockNumber_, uint40 timestamp_, GasData gasData_)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(nonce_, blockNumber_, timestamp_, gasData_));\n    }\n\n    // ═══════════════════════════════════════════════ STATE SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns a historical Merkle root from the Origin contract.\n    function root(State state) internal pure returns (bytes32) {\n        return state.unwrap().index({index_: OFFSET_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns domain of chain where the Origin contract is deployed.\n    function origin(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns nonce of Origin contract at the time, when `root` was the Merkle root.\n    function nonce(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when `root` was saved in Origin.\n    function blockNumber(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when `root` was saved in Origin.\n    /// @dev This is the timestamp according to the origin chain.\n    function timestamp(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n\n    /// @notice Returns gas data for the chain.\n    function gasData(State state) internal pure returns (GasData) {\n        return GasDataLib.wrapGasData(state.unwrap().indexUint({index_: OFFSET_GAS_DATA, bytes_: GAS_DATA_LENGTH}));\n    }\n}\n\n// contracts/libs/memory/BaseMessage.sol\n\n/// BaseMessage is a memory view over the base message supported by Origin-Destination\ntype BaseMessage is uint256;\n\nusing BaseMessageLib for BaseMessage global;\n\n/// BaseMessage structure represents a base message sent via the Origin-Destination contracts.\n/// - It only contains data relevant to the base message, the rest of data is encoded in the message header.\n/// - `sender` and `recipient` for EVM chains are EVM addresses casted to bytes32, while preserving left-alignment.\n/// - `tips` and `request` parameters are specified by a message sender\n/// \u003e Origin will calculate minimum tips for given request and content length, and will reject messages with tips\n/// lower than that.\n///\n/// # Memory layout of BaseMessage fields\n///\n/// | Position   | Field     | Type    | Bytes | Description                            |\n/// | ---------- | --------- | ------- | ----- | -------------------------------------- |\n/// | [000..032) | tips      | uint256 | 32    | Encoded tips paid on origin chain      |\n/// | [032..064) | sender    | bytes32 | 32    | Sender address on origin chain         |\n/// | [064..096) | recipient | bytes32 | 32    | Recipient address on destination chain |\n/// | [096..116) | request   | uint160 | 20    | Encoded request for message execution  |\n/// | [104..AAA) | content   | bytes   | ??    | Content to be passed to recipient      |\nlibrary BaseMessageLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_TIPS = 0;\n    uint256 private constant OFFSET_SENDER = 32;\n    uint256 private constant OFFSET_RECIPIENT = 64;\n    uint256 private constant OFFSET_REQUEST = OFFSET_RECIPIENT + TIPS_LENGTH;\n    uint256 private constant OFFSET_CONTENT = OFFSET_REQUEST + REQUEST_LENGTH;\n\n    // ═══════════════════════════════════════════════ BASE MESSAGE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted BaseMessage payload with provided fields.\n     * @param tips_         Encoded tips information\n     * @param sender_       Sender address on origin chain\n     * @param recipient_    Recipient address on destination chain\n     * @param request_      Encoded request for message execution\n     * @param content_      Raw content to be passed to recipient on destination chain\n     * @return Formatted base message\n     */\n    function formatBaseMessage(Tips tips_, bytes32 sender_, bytes32 recipient_, Request request_, bytes memory content_)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return abi.encodePacked(tips_, sender_, recipient_, request_, content_);\n    }\n\n    /**\n     * @notice Returns a BaseMessage view over the given payload.\n     * @dev Will revert if the payload is not a base message.\n     */\n    function castToBaseMessage(bytes memory payload) internal pure returns (BaseMessage) {\n        return castToBaseMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a BaseMessage view.\n     * @dev Will revert if the memory view is not over a base message payload.\n     */\n    function castToBaseMessage(MemView memView) internal pure returns (BaseMessage) {\n        if (!isBaseMessage(memView)) revert UnformattedBaseMessage();\n        return BaseMessage.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted BaseMessage.\n    function isBaseMessage(MemView memView) internal pure returns (bool) {\n        // Check if sender, recipient, tips fields exist\n        return (memView.len() \u003e= OFFSET_CONTENT);\n        // Content could be empty, so we don't check that\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(BaseMessage baseMessage) internal pure returns (MemView) {\n        return MemView.wrap(BaseMessage.unwrap(baseMessage));\n    }\n\n    /// @notice Returns baseMessage's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        // We hash \"tips\" and \"everything but tips\" to make tips proofs easier to verify\n        return MerkleMath.getParent(baseMessage.tips().leaf(), baseMessage.bodyLeaf());\n    }\n\n    /// @notice Returns hash for the \"everything but tips\" part of the base message.\n    function bodyLeaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_SENDER}).keccak();\n    }\n\n    // ═══════════════════════════════════════════ BASE MESSAGE SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips paid on origin chain.\n    function tips(BaseMessage baseMessage) internal pure returns (Tips) {\n        return TipsLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_TIPS, bytes_: TIPS_LENGTH})));\n    }\n\n    /// @notice Returns sender address on origin chain.\n    function sender(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_SENDER, bytes_: 32});\n    }\n\n    /// @notice Returns recipient address on destination chain.\n    function recipient(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_RECIPIENT, bytes_: 32});\n    }\n\n    /// @notice Returns an encoded request for message execution on destination chain.\n    function request(BaseMessage baseMessage) internal pure returns (Request) {\n        return RequestLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_REQUEST, bytes_: REQUEST_LENGTH})));\n    }\n\n    /// @notice Returns an untyped memory view over the content to be passed to recipient.\n    function content(BaseMessage baseMessage) internal pure returns (MemView) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_CONTENT});\n    }\n}\n\n// contracts/base/MessagingBase.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for all messaging contracts.\n * - Provides context on the local chain's domain.\n * - Provides ownership functionality.\n * - Will be providing pausing functionality when it is implemented.\n */\nabstract contract MessagingBase is MultiCallable, Versioned, Ownable2StepUpgradeable {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @notice Domain of the local chain, set once upon contract creation\n    uint32 public immutable localDomain;\n    // @notice Domain of the Synapse chain, set once upon contract creation\n    uint32 public immutable synapseDomain;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev gap for upgrade safety\n    uint256[50] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    constructor(string memory version_, uint32 synapseDomain_) Versioned(version_) {\n        localDomain = ChainContext.chainId();\n        synapseDomain = synapseDomain_;\n    }\n\n    // TODO: Implement pausing\n\n    /**\n     * @dev Should be impossible to renounce ownership;\n     * we override OpenZeppelin OwnableUpgradeable's\n     * implementation of renounceOwnership to make it a no-op\n     */\n    function renounceOwnership() public override onlyOwner {} //solhint-disable-line no-empty-blocks\n}\n\n// contracts/libs/memory/Message.sol\n\n/// Message is a memory over over a formatted message payload.\ntype Message is uint256;\n\nusing MessageLib for Message global;\n\n/// Library for formatting the various messages supported by Origin and Destination.\n///\n/// # Message memory layout\n///\n/// | Position   | Field  | Type    | Bytes | Description                                             |\n/// | ---------- | ------ | ------- | ----- | ------------------------------------------------------- |\n/// | [000..017) | header | uint136 | 17    | Encoded general routing information for the message     |\n/// | [017..AAA) | body   | bytes   | ??    | Formatted payload (according to flag) with message body |\nlibrary MessageLib {\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MemViewLib for bytes;\n    using HeaderLib for MemView;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_HEADER = 0;\n    uint256 private constant OFFSET_BODY = OFFSET_HEADER + HEADER_LENGTH;\n\n    // ══════════════════════════════════════════════════ MESSAGE ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns formatted message with provided fields.\n     * @param header_   Encoded general routing information for the message\n     * @param body_     Formatted payload (according to flag) with message body\n     * @return Formatted message\n     */\n    function formatMessage(Header header_, bytes memory body_) internal pure returns (bytes memory) {\n        return abi.encodePacked(header_, body_);\n    }\n\n    /**\n     * @notice Returns a Message view over for the given payload.\n     * @dev Will revert if the payload is not a message payload.\n     */\n    function castToMessage(bytes memory payload) internal pure returns (Message) {\n        return castToMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Message view.\n     * @dev Will revert if the memory view is not over a message payload.\n     */\n    function castToMessage(MemView memView) internal pure returns (Message) {\n        if (!isMessage(memView)) revert UnformattedMessage();\n        return Message.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Message.\n     */\n    function isMessage(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Check if headers exist in the payload\n        if (length \u003c OFFSET_BODY) return false;\n        // Check that Header is valid\n        uint256 paddedHeader = _header(memView);\n        if (!HeaderLib.isHeader(paddedHeader)) return false;\n        // Check that body is formatted according to the flag\n        // Only Base/Manager message flags exist\n        if (HeaderLib.wrapPadded(paddedHeader).flag() == MessageFlag.Base) {\n            // Check if body is a formatted base message\n            return _body(memView).isBaseMessage();\n        } else {\n            // Check if body is a formatted calldata for AgentManager call\n            return _body(memView).isCallData();\n        }\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Message message) internal pure returns (MemView) {\n        return MemView.wrap(Message.unwrap(message));\n    }\n\n    /// @notice Returns message's hash: a leaf to be inserted in the Merkle tree.\n    function leaf(Message message) internal pure returns (bytes32) {\n        // We hash header and body separately to make message proofs easier to verify\n        Header header_ = message.header();\n        // Only Base/Manager message flags exist\n        if (header_.flag() == MessageFlag.Base) {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToBaseMessage().leaf());\n        } else {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToCallData().leaf());\n        }\n    }\n\n    // ══════════════════════════════════════════════ MESSAGE SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns message's encoded header field.\n    function header(Message message) internal pure returns (Header) {\n        return HeaderLib.wrapPadded((message.unwrap().indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH})));\n    }\n\n    /// @notice Returns message's body field as an untyped memory view.\n    function body(Message message) internal pure returns (MemView) {\n        MemView memView = message.unwrap();\n        return _body(memView);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns message's padded header without checking that it is a valid header.\n    function _header(MemView memView) private pure returns (uint256) {\n        return memView.indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH});\n    }\n\n    /// @dev Returns an untyped memory view over the body field without checking\n    /// if the whole payload or the body are properly formatted.\n    function _body(MemView memView) private pure returns (MemView) {\n        return memView.sliceFrom({index_: OFFSET_BODY});\n    }\n}\n\n// contracts/base/AgentSecured.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for messaging contracts that are secured by the agent manager.\n * `AgentSecured` relies on `AgentManager` to provide the following functionality:\n * - Keep track of agents and their statuses.\n * - Pass agent-signed statements that were verified by the agent manager.\n * - These statements are considered valid indefinitely, unless the agent is disputed.\n * - Disputes are opened and resolved by the agent manager.\n * \u003e `AgentSecured` implementation should never use statements signed by agents that are disputed.\n */\nabstract contract AgentSecured is MessagingBase, IAgentSecured {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    address public immutable agentManager;\n\n    /// @inheritdoc IAgentSecured\n    address public immutable inbox;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    // (agent index =\u003e their dispute status: flag, openedAt, resolvedAt)\n    mapping(uint32 =\u003e DisputeStatus) internal _disputes;\n\n    /// @dev gap for upgrade safety\n    uint256[49] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    modifier onlyAgentManager() {\n        if (msg.sender != agentManager) revert CallerNotAgentManager();\n        _;\n    }\n\n    modifier onlyInbox() {\n        if (msg.sender != inbox) revert CallerNotInbox();\n        _;\n    }\n\n    constructor(string memory version_, uint32 synapseDomain_, address agentManager_, address inbox_)\n        MessagingBase(version_, synapseDomain_)\n    {\n        agentManager = agentManager_;\n        inbox = inbox_;\n    }\n\n    // ════════════════════════════════════════════ ONLY AGENT MANAGER ═════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external onlyAgentManager {\n        uint40 openedAt = ChainContext.blockTimestamp();\n        DisputeStatus memory status = DisputeStatus({flag: DisputeFlag.Pending, openedAt: openedAt, resolvedAt: 0});\n        _disputes[guardIndex] = status;\n        _disputes[notaryIndex] = status;\n    }\n\n    /// @inheritdoc IAgentSecured\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external onlyAgentManager {\n        // Update the dispute status of the slashed agent first.\n        uint40 resolvedAt = ChainContext.blockTimestamp();\n        _disputes[slashedIndex].flag = DisputeFlag.Slashed;\n        _disputes[slashedIndex].resolvedAt = resolvedAt;\n        // Mark the rival agent as not disputed, if there was an ongoing dispute.\n        if (rivalIndex != 0) {\n            _disputes[rivalIndex].flag = DisputeFlag.None;\n            _disputes[rivalIndex].resolvedAt = resolvedAt;\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function agentStatus(address agent) external view returns (AgentStatus memory) {\n        return _agentStatus(agent);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status) {\n        return _getAgent(index);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory) {\n        return _disputes[agentIndex];\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns status of the given agent: (flag, domain, index).\n    function _agentStatus(address agent) internal view returns (AgentStatus memory) {\n        return IAgentManager(agentManager).agentStatus(agent);\n    }\n\n    /// @dev Returns agent and their status for a given agent index. Returns zero values for non existing indexes.\n    function _getAgent(uint256 index) internal view returns (address agent, AgentStatus memory status) {\n        return IAgentManager(agentManager).getAgent(index);\n    }\n\n    /// @dev Checks if a Dispute exists for the given Notary. This function returns true, if\n    /// Notary is in ongoing Dispute, or if Dispute was resolved not in Notary's favor.\n    /// In both cases we can't trust Notary's data.\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeExists(uint32 notaryIndex) internal view returns (bool) {\n        return _disputes[notaryIndex].flag != DisputeFlag.None;\n    }\n\n    /// @dev Checks if a Notary recently won a Dispute and is still in the \"post-dispute\" timeout period.\n    /// In this period we still can't trust Notary's data, though we can optimistically assume that\n    /// that the data will be correct after the timeout (assuming no new Disputes are opened).\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeTimeout(uint32 notaryIndex) internal view returns (bool) {\n        DisputeStatus memory status = _disputes[notaryIndex];\n        // Exit early if Notary is in ongoing Dispute / slashed.\n        if (status.flag != DisputeFlag.None) return false;\n        // Check if Notary has been in any Dispute at all.\n        if (status.openedAt == 0) return false;\n        // Otherwise check if the Dispute timeout is still active.\n        return block.timestamp \u003c status.resolvedAt + DISPUTE_TIMEOUT_NOTARY;\n    }\n}\n\n// contracts/hubs/StateHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StateHub` is a parent contract for `Origin`. It is responsible for the following:\n/// - Keeping track of the historical Origin Merkle Tree containing all the message hashes.\n/// - Keeping track of the historical Origin States, as well as verifying their validity.\nabstract contract StateHub is AgentSecured, StateHubEvents, IStateHub {\n    using SafeCast for uint256;\n    using StateLib for bytes;\n\n    struct OriginState {\n        uint40 blockNumber;\n        uint40 timestamp;\n        GasData gasData;\n    }\n    // Bits left for tight packing: 80\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Historical Merkle Tree\n    /// Note: Takes two storage slots\n    HistoricalTree private _tree;\n\n    /// @dev All historical contract States\n    OriginState[] private _originStates;\n\n    /// @dev gap for upgrade safety\n    uint256[47] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IStateHub\n    function isValidState(bytes memory statePayload) external view returns (bool isValid) {\n        // This will revert if payload is not a formatted state\n        State state = statePayload.castToState();\n        return _isValidState(state);\n    }\n\n    /// @inheritdoc IStateHub\n    function statesAmount() external view returns (uint256) {\n        return _originStates.length;\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestLatestState() external view returns (bytes memory stateData) {\n        // This never underflows, assuming the contract was initialized\n        return suggestState(_nextNonce() - 1);\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestState(uint32 nonce) public view returns (bytes memory stateData) {\n        // This will revert if nonce is out of range\n        bytes32 root = _tree.root(nonce);\n        return _formatOriginState(_originStates[nonce], root, localDomain, nonce);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Initializes the saved states list by inserting a state for an empty Merkle Tree.\n    function _initializeStates() internal {\n        // This should only be called once, when the contract is initialized\n        // This will revert if _tree.roots is non-empty\n        bytes32 savedRoot = _tree.initializeRoots();\n        // Save root for empty merkle _tree with block number and timestamp of initialization\n        _saveState(savedRoot, _toOriginState());\n    }\n\n    /// @dev Inserts leaf into the Merkle Tree and saves the updated origin State.\n    function _insertAndSave(bytes32 leaf) internal {\n        bytes32 newRoot = _tree.insert(leaf);\n        _saveState(newRoot, _toOriginState());\n    }\n\n    /// @dev Saves an updated state of the Origin contract\n    function _saveState(bytes32 root, OriginState memory state) internal {\n        uint32 nonce = _nextNonce();\n        _originStates.push(state);\n        // Emit event with raw state data\n        emit StateSaved(_formatOriginState(state, root, localDomain, nonce));\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns nonce of the next sent message: the amount of saved States so far.\n    /// This always equals to \"total amount of sent messages\" plus 1.\n    function _nextNonce() internal view returns (uint32) {\n        // TODO: consider using more than 32 bits for origin nonces\n        return _originStates.length.toUint32();\n    }\n\n    /// @dev Checks if a state is valid, i.e. if it matches the historical one.\n    /// Reverts, if state refers to another Origin contract.\n    function _isValidState(State state) internal view returns (bool) {\n        // Check if state refers to this contract\n        if (state.origin() != localDomain) revert IncorrectOriginDomain();\n        // Check if nonce exists\n        uint32 nonce = state.nonce();\n        if (nonce \u003e= _originStates.length) return false;\n        // Check if state root matches the historical one\n        if (state.root() != _tree.root(nonce)) return false;\n        // Check if state metadata matches the historical one\n        return _areEqual(state, _originStates[nonce]);\n    }\n\n    // ═════════════════════════════════════════════ STRUCT FORMATTING ═════════════════════════════════════════════════\n\n    /// @dev Returns a formatted payload for a stored OriginState.\n    function _formatOriginState(OriginState memory originState, bytes32 root, uint32 origin, uint32 nonce)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return StateLib.formatState({\n            root_: root,\n            origin_: origin,\n            nonce_: nonce,\n            blockNumber_: originState.blockNumber,\n            timestamp_: originState.timestamp,\n            gasData_: originState.gasData\n        });\n    }\n\n    /// @dev Child contract should implement the logic for getting the current gas data from the gas oracle\n    /// to be saved as part of the Origin State.\n    // solhint-disable-next-line ordering\n    function _fetchGasData() internal view virtual returns (GasData);\n\n    /// @dev Returns a OriginState struct to save in the contract.\n    function _toOriginState() internal view returns (OriginState memory originState) {\n        originState.blockNumber = ChainContext.blockNumber();\n        originState.timestamp = ChainContext.blockTimestamp();\n        originState.gasData = _fetchGasData();\n    }\n\n    /// @dev Checks that a state and its Origin representation are equal.\n    function _areEqual(State state, OriginState memory originState) internal pure returns (bool) {\n        return state.blockNumber() == originState.blockNumber \u0026\u0026 state.timestamp() == originState.timestamp;\n    }\n}\n\n// contracts/Origin.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Origin` contract is used for sending messages to remote chains. It is done\n/// by inserting the message hashes into the Origin Merkle, which makes it possible to\n/// prove that message was sent using the Merkle proof against the Origin Merkle Root. This essentially\n/// compresses the list of messages into a single 32-byte value that needs to be stored on the destination chain.\n/// `Origin` is responsible for the following:\n/// - Formatting the sent message payloads, and inserting their hashes into the Origin Merkle Tree.\n/// - Keeping track of its own historical states (see parent contract `StateHub`).\n/// - Enforcing minimum tip values for sent base messages based on the provided execution requests.\n/// - Distributing the collected tips upon request from a local `AgentManager` contract.\ncontract Origin is StateHub, OriginEvents, InterfaceOrigin {\n    using MemViewLib for bytes;\n    using MessageLib for bytes;\n    using TipsLib for bytes;\n    using TypeCasts for address;\n\n    address public immutable gasOracle;\n\n    modifier onlyRemoteDestination(uint32 destination) {\n        if (destination == localDomain) revert IncorrectDestinationDomain();\n        _;\n    }\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_, address gasOracle_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {\n        gasOracle = gasOracle_;\n    }\n\n    /// @notice Initializes Origin contract:\n    /// - msg.sender is set as contract owner\n    /// - State of \"empty merkle tree\" is saved\n    function initialize() external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize \"states\": state of an \"empty merkle tree\" is saved\n        _initializeStates();\n    }\n\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable onlyRemoteDestination(destination) returns (uint32 messageNonce, bytes32 messageHash) {\n        // Check that content is not too large\n        if (content.length \u003e MAX_CONTENT_BYTES) revert ContentLengthTooBig();\n        // This will revert if msg.value is lower than value of minimum tips\n        Tips tips = _getMinimumTips(destination, paddedRequest, content.length).matchValue(msg.value);\n        Request request = RequestLib.wrapPadded(paddedRequest);\n        // Format the BaseMessage body\n        bytes memory body = BaseMessageLib.formatBaseMessage({\n            sender_: msg.sender.addressToBytes32(),\n            recipient_: recipient,\n            tips_: tips,\n            request_: request,\n            content_: content\n        });\n        // Send the message\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Base, body);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        onlyAgentManager\n        onlyRemoteDestination(destination)\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // AgentManager (checked via modifier) is responsible for constructing the calldata payload correctly.\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Manager, payload);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function withdrawTips(address recipient, uint256 amount) external onlyAgentManager {\n        if (address(this).balance \u003c amount) revert InsufficientEthBalance();\n        (bool success,) = recipient.call{value: amount}(\"\");\n        if (!success) revert EthTransferFailed();\n        emit TipWithdrawalCompleted(recipient, amount);\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue)\n    {\n        return _getMinimumTips(destination, paddedRequest, contentLength).value();\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Sends the given message to the specified destination. Message hash is inserted\n    /// into the Origin Merkle Tree, which will enable message execution on destination chain.\n    function _sendMessage(uint32 destination, uint32 optimisticPeriod, MessageFlag flag, bytes memory body)\n        internal\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // Format the message header\n        messageNonce = _nextNonce();\n        Header header = flag.encodeHeader({\n            origin_: localDomain,\n            nonce_: messageNonce,\n            destination_: destination,\n            optimisticPeriod_: optimisticPeriod\n        });\n        // Format the full message payload\n        bytes memory msgPayload = MessageLib.formatMessage(header, body);\n        // Insert new leaf into the Origin Merkle Tree and save the updated state\n        messageHash = msgPayload.castToMessage().leaf();\n        _insertAndSave(messageHash);\n        // Emit event with message information\n        emit Sent(messageHash, messageNonce, destination, msgPayload);\n        // Update the gas oracle data. We do this after the provided tips are checked so that\n        // the provided message is sent in the event that the gas oracle data is updated to a higher value.\n        InterfaceGasOracle(gasOracle).updateGasData(destination);\n        // TODO: consider doing this before the message is sent, while adjusting GasOracle.getMinimumTips() to\n        // use the pending gas oracle data.\n    }\n\n    /// @dev Returns the minimum tips for sending a message to the given destination with the given request and content.\n    function _getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        internal\n        view\n        returns (Tips)\n    {\n        return\n            TipsLib.wrapPadded(InterfaceGasOracle(gasOracle).getMinimumTips(destination, paddedRequest, contentLength));\n    }\n\n    /// @dev Gets the current gas data from the gas oracle to be saved as part of the Origin State.\n    function _fetchGasData() internal view override returns (GasData) {\n        return GasDataLib.wrapGasData(InterfaceGasOracle(gasOracle).getGasData());\n    }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"198749:5074:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;198749:5074:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"198749:5074:0:-:0;;;;;;;;","abiDefinition":[],"userDoc":{"kind":"user","methods":{},"notice":"Library for formatting the various messages supported by Origin and Destination. # Message memory layout | Position   | Field  | Type    | Bytes | Description                                             | | ---------- | ------ | ------- | ----- | ------------------------------------------------------- | | [000..017) | header | uint136 | 17    | Encoded general routing information for the message     | | [017..AAA) | body   | bytes   | ??    | Formatted payload (according to flag) with message body |","version":1},"developerDoc":{"kind":"dev","methods":{},"stateVariables":{"OFFSET_HEADER":{"details":"The variables below are not supposed to be used outside of the library directly."}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"stateVariables\":{\"OFFSET_HEADER\":{\"details\":\"The variables below are not supposed to be used outside of the library directly.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"Library for formatting the various messages supported by Origin and Destination. # Message memory layout | Position   | Field  | Type    | Bytes | Description                                             | | ---------- | ------ | ------- | ----- | ------------------------------------------------------- | | [000..017) | header | uint136 | 17    | Encoded general routing information for the message     | | [017..AAA) | body   | bytes   | ??    | Formatted payload (according to flag) with message body |\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Origin.sol\":\"MessageLib\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Origin.sol\":{\"keccak256\":\"0x96775924f147f3d1f8df8cdf56731fe52a15af8d8e12e608efb8158c112b18cd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e642a27f5fab3c62b4c02e9754e9e42b1cf2e5381dbea9d3d106d23b7772ebe6\",\"dweb:/ipfs/QmUwn7ZyBvPkjnMuK8ZMSexBUdNQnVtxwyoAyT4DXLQjra\"]}},\"version\":1}"},"hashes":{}},"solidity/Origin.sol:MessagingBase":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/OriginEvents.sol\n\n/// @notice A collection of events emitted by the Origin contract\nabstract contract OriginEvents {\n    /**\n     * @notice Emitted when a new message is sent.\n     * @param messageHash   Hash of message; the leaf inserted to the Merkle tree for the message\n     * @param nonce         Nonce of sent message (starts from 1)\n     * @param destination   Destination domain\n     * @param message       Raw bytes of message\n     */\n    event Sent(bytes32 indexed messageHash, uint32 indexed nonce, uint32 indexed destination, bytes message);\n\n    /**\n     * @notice Emitted when a tip withdrawal is completed.\n     * @param actor     Actor address\n     * @param tip       Tip value, denominated in local domain's wei\n     */\n    event TipWithdrawalCompleted(address actor, uint256 tip);\n}\n\n// contracts/events/StateHubEvents.sol\n\n/// @notice A collection of events emitted by the StateHub contract\nabstract contract StateHubEvents {\n    /**\n     * @notice Emitted when a new Origin State is saved after a message was sent.\n     * @param state     Raw payload with state data\n     */\n    event StateSaved(bytes state);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n    /**\n     * @notice Check that a given state is valid: matches the historical state of Origin contract.\n     * Note: any Agent including an invalid state in their snapshot will be slashed\n     * upon providing the snapshot and agent signature for it to Origin contract.\n     * @dev Will revert if any of these is true:\n     *  - State payload is not properly formatted.\n     * @param statePayload      Raw payload with state data\n     * @return isValid          Whether the provided state is valid\n     */\n    function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns the amount of saved states so far.\n     * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n     */\n    function statesAmount() external view returns (uint256);\n\n    /**\n     * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @return statePayload     Raw payload with the latest state data\n     */\n    function suggestLatestState() external view returns (bytes memory statePayload);\n\n    /**\n     * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @param nonce             Historical nonce to form a state\n     * @return statePayload     Raw payload with historical state data\n     */\n    function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/InterfaceGasOracle.sol\n\ninterface InterfaceGasOracle {\n    /**\n     * @notice Fetches the latest gas data for the chain from `Destination` contract,\n     * and uses it to update the oracle values for the requested chain.\n     * @param domain    Domain to update the gas data for\n     */\n    function updateGasData(uint32 domain) external;\n\n    /**\n     * @notice Returns the gas data for the local chain.\n     */\n    function getGasData() external view returns (uint256 paddedGasData);\n\n    /**\n     * @notice Returns the gas data for the given domain, in the decoded format.\n     * @param domain        Domain of chain to get gas data for\n     * @return gasPrice     Gas price for the chain (in Wei per gas unit)\n     * @return dataPrice    Calldata price (in Wei per byte of content)\n     * @return execBuffer   Tx fee safety buffer for message execution (in Wei)\n     * @return amortAttCost Amortized cost for attestation submission (in Wei)\n     * @return etherPrice   Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n     * @return markup       Markup for the message execution (in BWAD)\n     */\n    function getDecodedGasData(uint32 domain)\n        external\n        view\n        returns (\n            uint256 gasPrice,\n            uint256 dataPrice,\n            uint256 execBuffer,\n            uint256 amortAttCost,\n            uint256 etherPrice,\n            uint256 markup\n        );\n\n    /**\n     * @notice Returns the minimum tips for sending a message to a given destination.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return paddedTips       Padded encoded minimum tips information\n     */\n    function getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 paddedTips);\n}\n\n// contracts/interfaces/InterfaceOrigin.sol\n\ninterface InterfaceOrigin {\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /**\n     * @notice Send a message to the recipient located on destination domain.\n     * @dev Recipient has to conform to IMessageRecipient interface, otherwise message won't be delivered.\n     * Will revert if any of these is true:\n     * - `destination` is equal to contract's local domain\n     * - `content` length is greater than `MAX_CONTENT_BYTES`\n     * - `msg.value` is lower than value of minimum tips for the given message\n     * @param destination           Domain of destination chain\n     * @param recipient             Address of recipient on destination chain as bytes32\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param paddedRequest         Padded encoded message execution request on destination chain\n     * @param content               Raw bytes content of message\n     * @return messageNonce         Nonce of the sent message\n     * @return messageHash          Hash of the sent message\n     */\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable returns (uint32 messageNonce, bytes32 messageHash);\n\n    /**\n     * @notice Send a manager message to the destination domain.\n     * @dev This could only be called by AgentManager, which takes care of encoding the calldata payload.\n     * Note: (msgOrigin, proofMaturity) security args will be added to payload on the destination chain\n     * so that the AgentManager could verify where the Manager Message came from and how mature is the proof.\n     * Note: function is not payable, as no tips are required for sending a manager message.\n     * Will revert if `destination` is equal to contract's local domain.\n     * @param destination           Domain of destination chain\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param payload               Payload for calling AgentManager on destination chain (with extra security args)\n     */\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        returns (uint32 messageNonce, bytes32 messageHash);\n\n    // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Withdraws locked base message tips to the recipient.\n     * @dev Could only be called by a local AgentManager.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function withdrawTips(address recipient, uint256 amount) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the minimum tips value for sending a message to a given destination.\n     * @dev Using at least `tipsValue` as `msg.value` for `sendBaseMessage()`\n     * will guarantee that the message will be accepted.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return tipsValue        Minimum tips value for a message to be accepted\n     */\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue);\n}\n\n// contracts/libs/Constants.sol\n\n// Here we define common constants to enable their easier reusing later.\n\n// ══════════════════════════════════ MERKLE ═══════════════════════════════════\n/// @dev Height of the Agent Merkle Tree\nuint256 constant AGENT_TREE_HEIGHT = 32;\n/// @dev Height of the Origin Merkle Tree\nuint256 constant ORIGIN_TREE_HEIGHT = 32;\n/// @dev Height of the Snapshot Merkle Tree. Allows up to 64 leafs, e.g. up to 32 states\nuint256 constant SNAPSHOT_TREE_HEIGHT = 6;\n// ══════════════════════════════════ STRUCTS ══════════════════════════════════\n/// @dev See Attestation.sol: (bytes32,bytes32,uint32,uint40,uint40): 32+32+4+5+5\nuint256 constant ATTESTATION_LENGTH = 78;\n/// @dev See GasData.sol: (uint16,uint16,uint16,uint16,uint16,uint16): 2+2+2+2+2+2\nuint256 constant GAS_DATA_LENGTH = 12;\n/// @dev See Receipt.sol: (uint32,uint32,bytes32,bytes32,uint8,address,address,address): 4+4+32+32+1+20+20+20\nuint256 constant RECEIPT_LENGTH = 133;\n/// @dev See State.sol: (bytes32,uint32,uint32,uint40,uint40,GasData): 32+4+4+5+5+len(GasData)\nuint256 constant STATE_LENGTH = 50 + GAS_DATA_LENGTH;\n/// @dev Maximum amount of states in a single snapshot. Each state produces two leafs in the tree\nuint256 constant SNAPSHOT_MAX_STATES = 1 \u003c\u003c (SNAPSHOT_TREE_HEIGHT - 1);\n// ══════════════════════════════════ MESSAGE ══════════════════════════════════\n/// @dev See Header.sol: (uint8,uint32,uint32,uint32,uint32): 1+4+4+4+4\nuint256 constant HEADER_LENGTH = 17;\n/// @dev See Request.sol: (uint96,uint64,uint32): 12+8+4\nuint256 constant REQUEST_LENGTH = 24;\n/// @dev See Tips.sol: (uint64,uint64,uint64,uint64): 8+8+8+8\nuint256 constant TIPS_LENGTH = 32;\n/// @dev The amount of discarded last bits when encoding tip values\nuint256 constant TIPS_GRANULARITY = 32;\n/// @dev Tip values could be only the multiples of TIPS_MULTIPLIER\nuint256 constant TIPS_MULTIPLIER = 1 \u003c\u003c TIPS_GRANULARITY;\n// ══════════════════════════════ STATEMENT SALTS ══════════════════════════════\n/// @dev Salts for signing various statements\nbytes32 constant ATTESTATION_VALID_SALT = keccak256(\"ATTESTATION_VALID_SALT\");\nbytes32 constant ATTESTATION_INVALID_SALT = keccak256(\"ATTESTATION_INVALID_SALT\");\nbytes32 constant RECEIPT_VALID_SALT = keccak256(\"RECEIPT_VALID_SALT\");\nbytes32 constant RECEIPT_INVALID_SALT = keccak256(\"RECEIPT_INVALID_SALT\");\nbytes32 constant SNAPSHOT_VALID_SALT = keccak256(\"SNAPSHOT_VALID_SALT\");\nbytes32 constant STATE_INVALID_SALT = keccak256(\"STATE_INVALID_SALT\");\n// ═════════════════════════════════ PROTOCOL ══════════════════════════════════\n/// @dev Optimistic period for new agent roots in LightManager\nuint32 constant AGENT_ROOT_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Timeout between the agent root could be proposed and resolved in LightManager\nuint32 constant AGENT_ROOT_PROPOSAL_TIMEOUT = 12 hours;\nuint32 constant BONDING_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Amount of time that the Notary will not be considered active after they won a dispute\nuint32 constant DISPUTE_TIMEOUT_NOTARY = 12 hours;\n/// @dev Amount of time without fresh data from Notaries before contract owner can resolve stuck disputes manually\nuint256 constant FRESH_DATA_TIMEOUT = 4 hours;\n/// @dev Maximum bytes per message = 2 KiB (somewhat arbitrarily set to begin)\nuint256 constant MAX_CONTENT_BYTES = 2 * 2 ** 10;\n/// @dev Maximum value for the summit tip that could be set in GasOracle\nuint256 constant MAX_SUMMIT_TIP = 0.01 ether;\n\n// contracts/libs/Errors.sol\n\n// ══════════════════════════════ INVALID CALLER ═══════════════════════════════\n\nerror CallerNotAgentManager();\nerror CallerNotDestination();\nerror CallerNotInbox();\nerror CallerNotSummit();\n\n// ══════════════════════════════ INCORRECT DATA ═══════════════════════════════\n\nerror IncorrectAttestation();\nerror IncorrectAgentDomain();\nerror IncorrectAgentIndex();\nerror IncorrectAgentProof();\nerror IncorrectAgentRoot();\nerror IncorrectDataHash();\nerror IncorrectDestinationDomain();\nerror IncorrectOriginDomain();\nerror IncorrectSnapshotProof();\nerror IncorrectSnapshotRoot();\nerror IncorrectState();\nerror IncorrectStatesAmount();\nerror IncorrectTipsProof();\nerror IncorrectVersionLength();\n\nerror IncorrectNonce();\nerror IncorrectSender();\nerror IncorrectRecipient();\n\nerror FlagOutOfRange();\nerror IndexOutOfRange();\nerror NonceOutOfRange();\n\nerror OutdatedNonce();\n\nerror UnformattedAttestation();\nerror UnformattedAttestationReport();\nerror UnformattedBaseMessage();\nerror UnformattedCallData();\nerror UnformattedCallDataPrefix();\nerror UnformattedMessage();\nerror UnformattedReceipt();\nerror UnformattedReceiptReport();\nerror UnformattedSignature();\nerror UnformattedSnapshot();\nerror UnformattedState();\nerror UnformattedStateReport();\n\n// ═══════════════════════════════ MERKLE TREES ════════════════════════════════\n\nerror LeafNotProven();\nerror MerkleTreeFull();\nerror NotEnoughLeafs();\nerror TreeHeightTooLow();\n\n// ═════════════════════════════ OPTIMISTIC PERIOD ═════════════════════════════\n\nerror BaseClientOptimisticPeriod();\nerror MessageOptimisticPeriod();\nerror SlashAgentOptimisticPeriod();\nerror WithdrawTipsOptimisticPeriod();\nerror ZeroProofMaturity();\n\n// ═══════════════════════════════ AGENT MANAGER ═══════════════════════════════\n\nerror AgentNotGuard();\nerror AgentNotNotary();\n\nerror AgentCantBeAdded();\nerror AgentNotActive();\nerror AgentNotActiveNorUnstaking();\nerror AgentNotFraudulent();\nerror AgentNotUnstaking();\nerror AgentUnknown();\n\nerror AgentRootNotProposed();\nerror AgentRootTimeoutNotOver();\n\nerror NotStuck();\n\nerror DisputeAlreadyResolved();\nerror DisputeNotOpened();\nerror DisputeTimeoutNotOver();\nerror GuardInDispute();\nerror NotaryInDispute();\n\nerror MustBeSynapseDomain();\nerror SynapseDomainForbidden();\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\nerror AlreadyExecuted();\nerror AlreadyFailed();\nerror DuplicatedSnapshotRoot();\nerror IncorrectMagicValue();\nerror GasLimitTooLow();\nerror GasSuppliedTooLow();\n\n// ══════════════════════════════════ ORIGIN ═══════════════════════════════════\n\nerror ContentLengthTooBig();\nerror EthTransferFailed();\nerror InsufficientEthBalance();\n\n// ════════════════════════════════ GAS ORACLE ═════════════════════════════════\n\nerror LocalGasDataNotSet();\nerror RemoteGasDataNotSet();\n\n// ═══════════════════════════════════ TIPS ════════════════════════════════════\n\nerror SummitTipTooHigh();\nerror TipsClaimMoreThanEarned();\nerror TipsClaimZero();\nerror TipsOverflow();\nerror TipsValueTooLow();\n\n// ════════════════════════════════ MEMORY VIEW ════════════════════════════════\n\nerror IndexedTooMuch();\nerror ViewOverrun();\nerror OccupiedMemory();\nerror UnallocatedMemory();\nerror PrecompileOutOfGas();\n\n// ═════════════════════════════════ MULTICALL ═════════════════════════════════\n\nerror MulticallFailed();\n\n// contracts/libs/TypeCasts.sol\n\nlibrary TypeCasts {\n    // alignment preserving cast\n    function addressToBytes32(address addr) internal pure returns (bytes32) {\n        return bytes32(uint256(uint160(addr)));\n    }\n\n    // alignment preserving cast\n    function bytes32ToAddress(bytes32 buf) internal pure returns (address) {\n        return address(uint160(uint256(buf)));\n    }\n}\n\n// contracts/libs/stack/Number.sol\n\n/// Number is a compact representation of uint256, that is fit into 16 bits\n/// with the maximum relative error under 0.4%.\ntype Number is uint16;\n\nusing NumberLib for Number global;\n\n/// # Number\n/// Library for compact representation of uint256 numbers.\n/// - Number is stored using mantissa and exponent, each occupying 8 bits.\n/// - Numbers under 2**8 are stored as `mantissa` with `exponent = 0xFF`.\n/// - Numbers at least 2**8 are approximated as `(256 + mantissa) \u003c\u003c exponent`\n/// \u003e - `0 \u003c= mantissa \u003c 256`\n/// \u003e - `0 \u003c= exponent \u003c= 247` (`256 * 2**248` doesn't fit into uint256)\n/// # Number stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type  | Bytes |\n/// | ---------- | -------- | ----- | ----- |\n/// | (002..001] | mantissa | uint8 | 1     |\n/// | (001..000] | exponent | uint8 | 1     |\n\nlibrary NumberLib {\n    /// @dev Amount of bits to shift to mantissa field\n    uint16 private constant SHIFT_MANTISSA = 8;\n\n    /// @notice For bwad math (binary wad) we use 2**64 as \"wad\" unit.\n    /// @dev We are using not using 10**18 as wad, because it is not stored precisely in NumberLib.\n    uint256 internal constant BWAD_SHIFT = 64;\n    uint256 internal constant BWAD = 1 \u003c\u003c BWAD_SHIFT;\n    /// @notice ~0.1% in bwad units.\n    uint256 internal constant PER_MILLE_SHIFT = BWAD_SHIFT - 10;\n    uint256 internal constant PER_MILLE = 1 \u003c\u003c PER_MILLE_SHIFT;\n\n    /// @notice Compresses uint256 number into 16 bits.\n    function compress(uint256 value) internal pure returns (Number) {\n        // Find `msb` such as `2**msb \u003c= value \u003c 2**(msb + 1)`\n        uint256 msb = mostSignificantBit(value);\n        // We want to preserve 9 bits of precision.\n        // The highest bit is always 1, so we can skip it.\n        // The remaining 8 highest bits are stored as mantissa.\n        if (msb \u003c 8) {\n            // Value is less than 2**8, so we can use value as mantissa with \"-1\" exponent.\n            return _encode(uint8(value), 0xFF);\n        } else {\n            // We use `msb - 8` as exponent otherwise. Note that `exponent \u003e= 0`.\n            unchecked {\n                uint256 exponent = msb - 8;\n                // Shifting right by `msb-8` bits will shift the \"remaining 8 highest bits\" into the 8 lowest bits.\n                // uint8() will truncate the highest bit.\n                return _encode(uint8(value \u003e\u003e exponent), uint8(exponent));\n            }\n        }\n    }\n\n    /// @notice Decompresses 16 bits number into uint256.\n    /// @dev The outcome is an approximation of the original number: `(value - value / 256) \u003c number \u003c= value`.\n    function decompress(Number number) internal pure returns (uint256 value) {\n        // Isolate 8 highest bits as the mantissa.\n        uint256 mantissa = Number.unwrap(number) \u003e\u003e SHIFT_MANTISSA;\n        // This will truncate the highest bits, leaving only the exponent.\n        uint256 exponent = uint8(Number.unwrap(number));\n        if (exponent == 0xFF) {\n            return mantissa;\n        } else {\n            unchecked {\n                return (256 + mantissa) \u003c\u003c (exponent);\n            }\n        }\n    }\n\n    /// @dev Returns the most significant bit of `x`\n    /// https://solidity-by-example.org/bitwise/\n    function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\n        // To find `msb` we determine it bit by bit, starting from the highest one.\n        // `0 \u003c= msb \u003c= 255`, so we start from the highest bit, 1\u003c\u003c7 == 128.\n        // If `x` is at least 2**128, then the highest bit of `x` is at least 128.\n        // solhint-disable no-inline-assembly\n        assembly {\n            // `f` is set to 1\u003c\u003c7 if `x \u003e= 2**128` and to 0 otherwise.\n            let f := shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\n            // If `x \u003e= 2**128` then set `msb` highest bit to 1 and shift `x` right by 128.\n            // Otherwise, `msb` remains 0 and `x` remains unchanged.\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        // `x` is now at most 2**128 - 1. Continue the same way, the next highest bit is 1\u003c\u003c6 == 64.\n        assembly {\n            // `f` is set to 1\u003c\u003c6 if `x \u003e= 2**64` and to 0 otherwise.\n            let f := shl(6, gt(x, 0xFFFFFFFFFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c5 if `x \u003e= 2**32` and to 0 otherwise.\n            let f := shl(5, gt(x, 0xFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c4 if `x \u003e= 2**16` and to 0 otherwise.\n            let f := shl(4, gt(x, 0xFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c3 if `x \u003e= 2**8` and to 0 otherwise.\n            let f := shl(3, gt(x, 0xFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c2 if `x \u003e= 2**4` and to 0 otherwise.\n            let f := shl(2, gt(x, 0xF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c1 if `x \u003e= 2**2` and to 0 otherwise.\n            let f := shl(1, gt(x, 0x3))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1 if `x \u003e= 2**1` and to 0 otherwise.\n            let f := gt(x, 0x1)\n            msb := or(msb, f)\n        }\n    }\n\n    /// @dev Wraps (mantissa, exponent) pair into Number.\n    function _encode(uint8 mantissa, uint8 exponent) private pure returns (Number) {\n        // Casts below are upcasts, so they are safe.\n        return Number.wrap(uint16(mantissa) \u003c\u003c SHIFT_MANTISSA | uint16(exponent));\n    }\n}\n\n// contracts/libs/stack/Request.sol\n\n/// Request is encoded data with \"message execution request\".\ntype Request is uint192;\n\nusing RequestLib for Request global;\n\n/// Library for formatting _the request part_ of _the base messages_.\n/// - Request represents a message sender requirements for the message execution on the destination chain.\n/// - Request occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n/// \u003e gasDrop field is included for future compatibility and is ignored at the moment.\n///\n/// # Request stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type   | Bytes | Description                                          |\n/// | ---------- | -------- | ------ | ----- | ---------------------------------------------------- |\n/// | (024..012] | gasDrop  | uint96 | 12    | Minimum amount of gas token to drop to the recipient |\n/// | (012..004] | gasLimit | uint64 | 8     | Minimum amount of gas units to supply for execution  |\n/// | (004..000] | version  | uint32 | 4     | Base message version to pass to the recipient        |\n\nlibrary RequestLib {\n    /// @dev Amount of bits to shift to gasDrop field\n    uint192 private constant SHIFT_GAS_DROP = 12 * 8;\n    /// @dev Amount of bits to shift to gasLimit field\n    uint192 private constant SHIFT_GAS_LIMIT = 4 * 8;\n\n    /// @notice Returns an encoded request with the given fields\n    /// @param gasDrop_     Minimum amount of gas token to drop to the recipient (ignored at the moment)\n    /// @param gasLimit_    Minimum amount of gas units to supply for execution\n    /// @param version_     Base message version to pass to the recipient\n    function encodeRequest(uint96 gasDrop_, uint64 gasLimit_, uint32 version_) internal pure returns (Request) {\n        // Casts below are upcasts, so they are safe\n        return Request.wrap(uint192(gasDrop_) \u003c\u003c SHIFT_GAS_DROP | uint192(gasLimit_) \u003c\u003c SHIFT_GAS_LIMIT | version_);\n    }\n\n    /// @notice Wraps the padded encoded request into a Request-typed value.\n    /// @dev The \"padded\" request is simply an encoded request casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded requests\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedRequest) internal pure returns (Request) {\n        // Casting to uint192 will truncate the highest bits, which is the behavior we want\n        return Request.wrap(uint192(paddedRequest));\n    }\n\n    /// @notice Returns the requested of gas token to drop to the recipient.\n    function gasDrop(Request request) internal pure returns (uint96) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return uint96(Request.unwrap(request) \u003e\u003e SHIFT_GAS_DROP);\n    }\n\n    /// @notice Returns the requested minimum amount of gas units to supply for execution.\n    function gasLimit(Request request) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Request.unwrap(request) \u003e\u003e SHIFT_GAS_LIMIT);\n    }\n\n    /// @notice Returns the requested base message version to pass to the recipient.\n    function version(Request request) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Request.unwrap(request));\n    }\n}\n\n// node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        require(value \u003c= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        require(value \u003c= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        require(value \u003c= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value \u003c= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        require(value \u003c= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        require(value \u003c= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        require(value \u003c= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        require(value \u003c= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        require(value \u003c= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        require(value \u003c= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        require(value \u003c= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        require(value \u003c= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        require(value \u003c= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        require(value \u003c= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        require(value \u003c= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value \u003c= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        require(value \u003c= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        require(value \u003c= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        require(value \u003c= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value \u003c= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        require(value \u003c= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        require(value \u003c= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        require(value \u003c= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value \u003c= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        require(value \u003c= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        require(value \u003c= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        require(value \u003c= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value \u003c= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        require(value \u003c= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value \u003c= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value \u003c= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     *\n     * _Available since v3.0._\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value \u003e= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     *\n     * _Available since v3.0._\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value \u003c= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     *\n     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length \u003e 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance \u003e= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance \u003e= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length \u003e 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n\n// contracts/base/MultiCallable.sol\n\n/// @notice Collection of Multicall utilities. Fork of Multicall3:\n/// https://github.com/mds1/multicall/blob/master/src/Multicall3.sol\nabstract contract MultiCallable {\n    struct Call {\n        bool allowFailure;\n        bytes callData;\n    }\n\n    struct Result {\n        bool success;\n        bytes returnData;\n    }\n\n    /// @notice Aggregates a few calls to this contract into one multicall without modifying `msg.sender`.\n    function multicall(Call[] calldata calls) external returns (Result[] memory callResults) {\n        uint256 amount = calls.length;\n        callResults = new Result[](amount);\n        Call calldata call_;\n        for (uint256 i = 0; i \u003c amount;) {\n            call_ = calls[i];\n            Result memory result = callResults[i];\n            // We perform a delegate call to ourselves here. Delegate call does not modify `msg.sender`, so\n            // this will have the same effect as if `msg.sender` performed all the calls themselves one by one.\n            // solhint-disable-next-line avoid-low-level-calls\n            (result.success, result.returnData) = address(this).delegatecall(call_.callData);\n            // solhint-disable-next-line no-inline-assembly\n            assembly {\n                // Revert if the call fails and failure is not allowed\n                // `allowFailure := calldataload(call_)` and `success := mload(result)`\n                if iszero(or(calldataload(call_), mload(result))) {\n                    // Revert with `0x4d6a2328` (function selector for `MulticallFailed()`)\n                    mstore(0x00, 0x4d6a232800000000000000000000000000000000000000000000000000000000)\n                    revert(0x00, 0x04)\n                }\n            }\n            unchecked {\n                ++i;\n            }\n        }\n    }\n}\n\n// contracts/base/Version.sol\n\n/**\n * @title Versioned\n * @notice Version getter for contracts. Doesn't use any storage slots, meaning\n * it will never cause any troubles with the upgradeable contracts. For instance, this contract\n * can be added or removed from the inheritance chain without shifting the storage layout.\n */\nabstract contract Versioned {\n    /**\n     * @notice Struct that is mimicking the storage layout of a string with 32 bytes or less.\n     * Length is limited by 32, so the whole string payload takes two memory words:\n     * @param length    String length\n     * @param data      String characters\n     */\n    struct _ShortString {\n        uint256 length;\n        bytes32 data;\n    }\n\n    /// @dev Length of the \"version string\"\n    uint256 private immutable _length;\n    /// @dev Bytes representation of the \"version string\".\n    /// Strings with length over 32 are not supported!\n    bytes32 private immutable _data;\n\n    constructor(string memory version_) {\n        _length = bytes(version_).length;\n        if (_length \u003e 32) revert IncorrectVersionLength();\n        // bytes32 is left-aligned =\u003e this will store the byte representation of the string\n        // with the trailing zeroes to complete the 32-byte word\n        _data = bytes32(bytes(version_));\n    }\n\n    function version() external view returns (string memory versionString) {\n        // Load the immutable values to form the version string\n        _ShortString memory str = _ShortString(_length, _data);\n        // The only way to do this cast is doing some dirty assembly\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            versionString := str\n        }\n    }\n}\n\n// contracts/libs/ChainContext.sol\n\n/// @notice Library for accessing chain context variables as tightly packed integers.\n/// Messaging contracts should rely on this library for accessing chain context variables\n/// instead of doing the casting themselves.\nlibrary ChainContext {\n    using SafeCast for uint256;\n\n    /// @notice Returns the current block number as uint40.\n    /// @dev Reverts if block number is greater than 40 bits, which is not supposed to happen\n    /// until the block.timestamp overflows (assuming block time is at least 1 second).\n    function blockNumber() internal view returns (uint40) {\n        return block.number.toUint40();\n    }\n\n    /// @notice Returns the current block timestamp as uint40.\n    /// @dev Reverts if block timestamp is greater than 40 bits, which is\n    /// supposed to happen approximately in year 36835.\n    function blockTimestamp() internal view returns (uint40) {\n        return block.timestamp.toUint40();\n    }\n\n    /// @notice Returns the chain id as uint32.\n    /// @dev Reverts if chain id is greater than 32 bits, which is not\n    /// supposed to happen in production.\n    function chainId() internal view returns (uint32) {\n        return block.chainid.toUint32();\n    }\n}\n\n// contracts/libs/Structures.sol\n\n// Here we define common enums and structures to enable their easier reusing later.\n\n// ═══════════════════════════════ AGENT STATUS ════════════════════════════════\n\n/// @dev Potential statuses for the off-chain bonded agent:\n/// - Unknown: never provided a bond =\u003e signature not valid\n/// - Active: has a bond in BondingManager =\u003e signature valid\n/// - Unstaking: has a bond in BondingManager, initiated the unstaking =\u003e signature not valid\n/// - Resting: used to have a bond in BondingManager, successfully unstaked =\u003e signature not valid\n/// - Fraudulent: proven to commit fraud, value in Merkle Tree not updated =\u003e signature not valid\n/// - Slashed: proven to commit fraud, value in Merkle Tree was updated =\u003e signature not valid\n/// Unstaked agent could later be added back to THE SAME domain by staking a bond again.\n/// Honest agent: Unknown -\u003e Active -\u003e unstaking -\u003e Resting -\u003e Active ...\n/// Malicious agent: Unknown -\u003e Active -\u003e Fraudulent -\u003e Slashed\n/// Malicious agent: Unknown -\u003e Active -\u003e Unstaking -\u003e Fraudulent -\u003e Slashed\nenum AgentFlag {\n    Unknown,\n    Active,\n    Unstaking,\n    Resting,\n    Fraudulent,\n    Slashed\n}\n\n/// @notice Struct for storing an agent in the BondingManager contract.\nstruct AgentStatus {\n    AgentFlag flag;\n    uint32 domain;\n    uint32 index;\n}\n// 184 bits available for tight packing\n\nusing StructureUtils for AgentStatus global;\n\n/// @notice Potential statuses of an agent in terms of being in dispute\n/// - None: agent is not in dispute\n/// - Pending: agent is in unresolved dispute\n/// - Slashed: agent was in dispute that lead to agent being slashed\n/// Note: agent who won the dispute has their status reset to None\nenum DisputeFlag {\n    None,\n    Pending,\n    Slashed\n}\n\n/// @notice Struct for storing dispute status of an agent.\n/// @param flag         Dispute flag: None/Pending/Slashed.\n/// @param openedAt     Timestamp when the latest agent dispute was opened (zero if not opened).\n/// @param resolvedAt   Timestamp when the latest agent dispute was resolved (zero if not resolved).\nstruct DisputeStatus {\n    DisputeFlag flag;\n    uint40 openedAt;\n    uint40 resolvedAt;\n}\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\n/// @notice Struct representing the status of Destination contract.\n/// @param snapRootTime     Timestamp when latest snapshot root was accepted\n/// @param agentRootTime    Timestamp when latest agent root was accepted\n/// @param notaryIndex      Index of Notary who signed the latest agent root\nstruct DestinationStatus {\n    uint40 snapRootTime;\n    uint40 agentRootTime;\n    uint32 notaryIndex;\n}\n\n// ═══════════════════════════════ EXECUTION HUB ═══════════════════════════════\n\n/// @notice Potential statuses of the message in Execution Hub.\n/// - None: there hasn't been a valid attempt to execute the message yet\n/// - Failed: there was a valid attempt to execute the message, but recipient reverted\n/// - Success: there was a valid attempt to execute the message, and recipient did not revert\n/// Note: message can be executed until its status is Success\nenum MessageStatus {\n    None,\n    Failed,\n    Success\n}\n\nlibrary StructureUtils {\n    /// @notice Checks that Agent is Active\n    function verifyActive(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active) {\n            revert AgentNotActive();\n        }\n    }\n\n    /// @notice Checks that Agent is Unstaking\n    function verifyUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Unstaking) {\n            revert AgentNotUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Active or Unstaking\n    function verifyActiveUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active \u0026\u0026 status.flag != AgentFlag.Unstaking) {\n            revert AgentNotActiveNorUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Fraudulent\n    function verifyFraudulent(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Fraudulent) {\n            revert AgentNotFraudulent();\n        }\n    }\n\n    /// @notice Checks that Agent is not Unknown\n    function verifyKnown(AgentStatus memory status) internal pure {\n        if (status.flag == AgentFlag.Unknown) {\n            revert AgentUnknown();\n        }\n    }\n}\n\n// contracts/libs/memory/MemView.sol\n\n/// @dev MemView is an untyped view over a portion of memory to be used instead of `bytes memory`\ntype MemView is uint256;\n\n/// @dev Attach library functions to MemView\nusing MemViewLib for MemView global;\n\n/// @notice Library for operations with the memory views.\n/// Forked from https://github.com/summa-tx/memview-sol with several breaking changes:\n/// - The codebase is ported to Solidity 0.8\n/// - Custom errors are added\n/// - The runtime type checking is replaced with compile-time check provided by User-Defined Value Types\n///   https://docs.soliditylang.org/en/latest/types.html#user-defined-value-types\n/// - uint256 is used as the underlying type for the \"memory view\" instead of bytes29.\n///   It is wrapped into MemView custom type in order not to be confused with actual integers.\n/// - Therefore the \"type\" field is discarded, allowing to allocate 16 bytes for both view location and length\n/// - The documentation is expanded\n/// - Library functions unused by the rest of the codebase are removed\n//  - Very pretty code separators are added :)\nlibrary MemViewLib {\n    /// @notice Stack layout for uint256 (from highest bits to lowest)\n    /// (32 .. 16]      loc     16 bytes    Memory address of underlying bytes\n    /// (16 .. 00]      len     16 bytes    Length of underlying bytes\n\n    // ═══════════════════════════════════════════ BUILDING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Instantiate a new untyped memory view. This should generally not be called directly.\n     * Prefer `ref` wherever possible.\n     * @param loc_          The memory address\n     * @param len_          The length\n     * @return The new view with the specified location and length\n     */\n    function build(uint256 loc_, uint256 len_) internal pure returns (MemView) {\n        uint256 end_ = loc_ + len_;\n        // Make sure that a view is not constructed that points to unallocated memory\n        // as this could be indicative of a buffer overflow attack\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            if gt(end_, mload(0x40)) { end_ := 0 }\n        }\n        if (end_ == 0) {\n            revert UnallocatedMemory();\n        }\n        return _unsafeBuildUnchecked(loc_, len_);\n    }\n\n    /**\n     * @notice Instantiate a memory view from a byte array.\n     * @dev Note that due to Solidity memory representation, it is not possible to\n     * implement a deref, as the `bytes` type stores its len in memory.\n     * @param arr           The byte array\n     * @return The memory view over the provided byte array\n     */\n    function ref(bytes memory arr) internal pure returns (MemView) {\n        uint256 len_ = arr.length;\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 loc_;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // We add 0x20, so that the view starts exactly where the array data starts\n            loc_ := add(arr, 0x20)\n        }\n        return build(loc_, len_);\n    }\n\n    // ════════════════════════════════════════════ CLONING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to the new memory.\n     * @param memView       The memory view\n     * @return arr          The cloned byte array\n     */\n    function clone(MemView memView) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        unchecked {\n            _unsafeCopyTo(memView, ptr + 0x20);\n        }\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 len_ = memView.len();\n        uint256 footprint_ = memView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    /**\n     * @notice Copies all views, joins them into a new bytearray.\n     * @param memViews      The memory views\n     * @return arr          The new byte array with joined data behind the given views\n     */\n    function join(MemView[] memory memViews) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        MemView newView;\n        unchecked {\n            newView = _unsafeJoin(memViews, ptr + 0x20);\n        }\n        uint256 len_ = newView.len();\n        uint256 footprint_ = newView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    // ══════════════════════════════════════════ INSPECTING MEMORY VIEW ═══════════════════════════════════════════════\n\n    /**\n     * @notice Returns the memory address of the underlying bytes.\n     * @param memView       The memory view\n     * @return loc_         The memory address\n     */\n    function loc(MemView memView) internal pure returns (uint256 loc_) {\n        // loc is stored in the highest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u003e\u003e 128;\n    }\n\n    /**\n     * @notice Returns the number of bytes of the view.\n     * @param memView       The memory view\n     * @return len_         The length of the view\n     */\n    function len(MemView memView) internal pure returns (uint256 len_) {\n        // len is stored in the lowest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u0026 type(uint128).max;\n    }\n\n    /**\n     * @notice Returns the endpoint of `memView`.\n     * @param memView       The memory view\n     * @return end_         The endpoint of `memView`\n     */\n    function end(MemView memView) internal pure returns (uint256 end_) {\n        // The endpoint never overflows uint128, let alone uint256, so we could use unchecked math here\n        unchecked {\n            return memView.loc() + memView.len();\n        }\n    }\n\n    /**\n     * @notice Returns the number of memory words this memory view occupies, rounded up.\n     * @param memView       The memory view\n     * @return words_       The number of memory words\n     */\n    function words(MemView memView) internal pure returns (uint256 words_) {\n        // returning ceil(length / 32.0)\n        unchecked {\n            return (memView.len() + 31) \u003e\u003e 5;\n        }\n    }\n\n    /**\n     * @notice Returns the in-memory footprint of a fresh copy of the view.\n     * @param memView       The memory view\n     * @return footprint_   The in-memory footprint of a fresh copy of the view.\n     */\n    function footprint(MemView memView) internal pure returns (uint256 footprint_) {\n        // words() * 32\n        return memView.words() \u003c\u003c 5;\n    }\n\n    // ════════════════════════════════════════════ HASHING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the keccak256 hash of the underlying memory\n     * @param memView       The memory view\n     * @return digest       The keccak256 hash of the underlying memory\n     */\n    function keccak(MemView memView) internal pure returns (bytes32 digest) {\n        uint256 loc_ = memView.loc();\n        uint256 len_ = memView.len();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            digest := keccak256(loc_, len_)\n        }\n    }\n\n    /**\n     * @notice Adds a salt to the keccak256 hash of the underlying data and returns the keccak256 hash of the\n     * resulting data.\n     * @param memView       The memory view\n     * @return digestSalted keccak256(salt, keccak256(memView))\n     */\n    function keccakSalted(MemView memView, bytes32 salt) internal pure returns (bytes32 digestSalted) {\n        return keccak256(bytes.concat(salt, memView.keccak()));\n    }\n\n    // ════════════════════════════════════════════ SLICING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Safe slicing without memory modification.\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the given index\n     */\n    function slice(MemView memView, uint256 index_, uint256 len_) internal pure returns (MemView) {\n        uint256 loc_ = memView.loc();\n        // Ensure it doesn't overrun the view\n        if (loc_ + index_ + len_ \u003e memView.end()) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // loc_ + index_ \u003c= memView.end()\n            return build({loc_: loc_ + index_, len_: len_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing bytes from `index` to end(memView).\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @return The new view for the slice starting from the given index until the initial view endpoint\n     */\n    function sliceFrom(MemView memView, uint256 index_) internal pure returns (MemView) {\n        uint256 len_ = memView.len();\n        // Ensure it doesn't overrun the view\n        if (index_ \u003e len_) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // index_ \u003c= len_ =\u003e memView.loc() + index_ \u003c= memView.loc() + memView.len() == memView.end()\n            return build({loc_: memView.loc() + index_, len_: len_ - index_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the first `len` bytes.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the initial view beginning\n     */\n    function prefix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        return memView.slice({index_: 0, len_: len_});\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the last `len` byte.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length until the initial view endpoint\n     */\n    function postfix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        uint256 viewLen = memView.len();\n        // Ensure it doesn't overrun the view\n        if (len_ \u003e viewLen) {\n            revert ViewOverrun();\n        }\n        // Could do the unchecked math due to the check above\n        uint256 index_;\n        unchecked {\n            index_ = viewLen - len_;\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // len_ \u003c= memView.len() =\u003e memView.loc() \u003c= loc_ \u003c= memView.end()\n            return build({loc_: memView.loc() + viewLen - len_, len_: len_});\n        }\n    }\n\n    // ═══════════════════════════════════════════ INDEXING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Load up to 32 bytes from the view onto the stack.\n     * @dev Returns a bytes32 with only the `bytes_` HIGHEST bytes set.\n     * This can be immediately cast to a smaller fixed-length byte array.\n     * To automatically cast to an integer, use `indexUint`.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return result       The 32 byte result having only `bytes_` highest bytes set\n     */\n    function index(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (bytes32 result) {\n        if (bytes_ == 0) {\n            return bytes32(0);\n        }\n        // Can't load more than 32 bytes to the stack in one go\n        if (bytes_ \u003e 32) {\n            revert IndexedTooMuch();\n        }\n        // The last indexed byte should be within view boundaries\n        if (index_ + bytes_ \u003e memView.len()) {\n            revert ViewOverrun();\n        }\n        uint256 bitLength = bytes_ \u003c\u003c 3; // bytes_ * 8\n        uint256 loc_ = memView.loc();\n        // Get a mask with `bitLength` highest bits set\n        uint256 mask;\n        // 0x800...00 binary representation is 100...00\n        // sar stands for \"signed arithmetic shift\": https://en.wikipedia.org/wiki/Arithmetic_shift\n        // sar(N-1, 100...00) = 11...100..00, with exactly N highest bits set to 1\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            mask := sar(sub(bitLength, 1), 0x8000000000000000000000000000000000000000000000000000000000000000)\n        }\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load a full word using index offset, and apply mask to ignore non-relevant bytes\n            result := and(mload(add(loc_, index_)), mask)\n        }\n    }\n\n    /**\n     * @notice Parse an unsigned integer from the view at `index`.\n     * @dev Requires that the view have \u003e= `bytes_` bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return The unsigned integer\n     */\n    function indexUint(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (uint256) {\n        bytes32 indexedBytes = memView.index(index_, bytes_);\n        // `index()` returns left-aligned `bytes_`, while integers are right-aligned\n        // Shifting here to right-align with the full 32 bytes word: need to shift right `(32 - bytes_)` bytes\n        unchecked {\n            // memView.index() reverts when bytes_ \u003e 32, thus unchecked math\n            return uint256(indexedBytes) \u003e\u003e ((32 - bytes_) \u003c\u003c 3);\n        }\n    }\n\n    /**\n     * @notice Parse an address from the view at `index`.\n     * @dev Requires that the view have \u003e= 20 bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @return The address\n     */\n    function indexAddress(MemView memView, uint256 index_) internal pure returns (address) {\n        // index 20 bytes as `uint160`, and then cast to `address`\n        return address(uint160(memView.indexUint(index_, 20)));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns a memory view over the specified memory location\n    /// without checking if it points to unallocated memory.\n    function _unsafeBuildUnchecked(uint256 loc_, uint256 len_) private pure returns (MemView) {\n        // There is no scenario where loc or len would overflow uint128, so we omit this check.\n        // We use the highest 128 bits to encode the location and the lowest 128 bits to encode the length.\n        return MemView.wrap((loc_ \u003c\u003c 128) | len_);\n    }\n\n    /**\n     * @notice Copy the view to a location, return an unsafe memory reference\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memView       The memory view\n     * @param newLoc        The new location to copy the underlying view data\n     * @return The memory view over the unsafe memory with the copied underlying data\n     */\n    function _unsafeCopyTo(MemView memView, uint256 newLoc) private view returns (MemView) {\n        uint256 len_ = memView.len();\n        uint256 oldLoc = memView.loc();\n\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (newLoc \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        bool res;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // use the identity precompile (0x04) to copy\n            res := staticcall(gas(), 0x04, oldLoc, len_, newLoc, len_)\n        }\n        if (!res) revert PrecompileOutOfGas();\n        return _unsafeBuildUnchecked({loc_: newLoc, len_: len_});\n    }\n\n    /**\n     * @notice Join the views in memory, return an unsafe reference to the memory.\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memViews      The memory views\n     * @return The conjoined view pointing to the new memory\n     */\n    function _unsafeJoin(MemView[] memory memViews, uint256 location) private view returns (MemView) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (location \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        // Copy the views to the specified location one by one, by tracking the amount of copied bytes so far\n        uint256 offset = 0;\n        for (uint256 i = 0; i \u003c memViews.length;) {\n            MemView memView = memViews[i];\n            // We can use the unchecked math here as location + sum(view.length) will never overflow uint256\n            unchecked {\n                _unsafeCopyTo(memView, location + offset);\n                offset += memView.len();\n                ++i;\n            }\n        }\n        return _unsafeBuildUnchecked({loc_: location, len_: offset});\n    }\n}\n\n// contracts/libs/merkle/MerkleMath.sol\n\nlibrary MerkleMath {\n    // ═════════════════════════════════════════ BASIC MERKLE CALCULATIONS ═════════════════════════════════════════════\n\n    /**\n     * @notice Calculates the merkle root for the given leaf and merkle proof.\n     * @dev Will revert if proof length exceeds the tree height.\n     * @param index     Index of `leaf` in tree\n     * @param leaf      Leaf of the merkle tree\n     * @param proof     Proof of inclusion of `leaf` in the tree\n     * @param height    Height of the merkle tree\n     * @return root_    Calculated Merkle Root\n     */\n    function proofRoot(uint256 index, bytes32 leaf, bytes32[] memory proof, uint256 height)\n        internal\n        pure\n        returns (bytes32 root_)\n    {\n        // Proof length could not exceed the tree height\n        uint256 proofLen = proof.length;\n        if (proofLen \u003e height) revert TreeHeightTooLow();\n        root_ = leaf;\n        /// @dev Apply unchecked to all ++h operations\n        unchecked {\n            // Go up the tree levels from the leaf following the proof\n            for (uint256 h = 0; h \u003c proofLen; ++h) {\n                // Get a sibling node on current level: this is proof[h]\n                root_ = getParent(root_, proof[h], index, h);\n            }\n            // Go up to the root: the remaining siblings are EMPTY\n            for (uint256 h = proofLen; h \u003c height; ++h) {\n                root_ = getParent(root_, bytes32(0), index, h);\n            }\n        }\n    }\n\n    /**\n     * @notice Calculates the parent of a node on the path from one of the leafs to root.\n     * @param node          Node on a path from tree leaf to root\n     * @param sibling       Sibling for a given node\n     * @param leafIndex     Index of the tree leaf\n     * @param nodeHeight    \"Level height\" for `node` (ZERO for leafs, ORIGIN_TREE_HEIGHT for root)\n     */\n    function getParent(bytes32 node, bytes32 sibling, uint256 leafIndex, uint256 nodeHeight)\n        internal\n        pure\n        returns (bytes32 parent)\n    {\n        // Index for `node` on its \"tree level\" is (leafIndex / 2**height)\n        // \"Left child\" has even index, \"right child\" has odd index\n        if ((leafIndex \u003e\u003e nodeHeight) \u0026 1 == 0) {\n            // Left child\n            return getParent(node, sibling);\n        } else {\n            // Right child\n            return getParent(sibling, node);\n        }\n    }\n\n    /// @notice Calculates the parent of tow nodes in the merkle tree.\n    /// @dev We use implementation with H(0,0) = 0\n    /// This makes EVERY empty node in the tree equal to ZERO,\n    /// saving us from storing H(0,0), H(H(0,0), H(0, 0)), and so on\n    /// @param leftChild    Left child of the calculated node\n    /// @param rightChild   Right child of the calculated node\n    /// @return parent      Value for the node having above mentioned children\n    function getParent(bytes32 leftChild, bytes32 rightChild) internal pure returns (bytes32 parent) {\n        if (leftChild == bytes32(0) \u0026\u0026 rightChild == bytes32(0)) {\n            return 0;\n        } else {\n            return keccak256(bytes.concat(leftChild, rightChild));\n        }\n    }\n\n    // ════════════════════════════════ ROOT/PROOF CALCULATION FOR A LIST OF LEAFS ═════════════════════════════════════\n\n    /**\n     * @notice Calculates merkle root for a list of given leafs.\n     * Merkle Tree is constructed by padding the list with ZERO values for leafs until list length is `2**height`.\n     * Merkle Root is calculated for the constructed tree, and then saved in `leafs[0]`.\n     * \u003e Note:\n     * \u003e - `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * \u003e - Caller is expected not to reuse `hashes` list after the call, and only use `leafs[0]` value,\n     * which is guaranteed to contain the calculated merkle root.\n     * \u003e - root is calculated using the `H(0,0) = 0` Merkle Tree implementation. See MerkleTree.sol for details.\n     * @dev Amount of leaves should be at most `2**height`\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param height    Height of the Merkle Tree to construct\n     */\n    function calculateRoot(bytes32[] memory hashes, uint256 height) internal pure {\n        uint256 levelLength = hashes.length;\n        // Amount of hashes could not exceed amount of leafs in tree with the given height\n        if (levelLength \u003e (1 \u003c\u003c height)) revert TreeHeightTooLow();\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\": the amount of iterations for the for loop above.\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n            }\n        }\n    }\n\n    /**\n     * @notice Generates a proof of inclusion of a leaf in the list. If the requested index is outside\n     * of the list range, generates a proof of inclusion for an empty leaf (proof of non-inclusion).\n     * The Merkle Tree is constructed by padding the list with ZERO values until list length is a power of two\n     * __AND__ index is in the extended list range. For example:\n     *  - `hashes.length == 6` and `0 \u003c= index \u003c= 7` will \"extend\" the list to 8 entries.\n     *  - `hashes.length == 6` and `7 \u003c index \u003c= 15` will \"extend\" the list to 16 entries.\n     * \u003e Note: `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * Caller is expected not to reuse `hashes` list after the call.\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param index     Leaf index to generate the proof for\n     * @return proof    Generated merkle proof\n     */\n    function calculateProof(bytes32[] memory hashes, uint256 index) internal pure returns (bytes32[] memory proof) {\n        // Use only meaningful values for the shortened proof\n        // Check if index is within the list range (we want to generates proofs for outside leafs as well)\n        uint256 height = getHeight(index \u003c hashes.length ? hashes.length : (index + 1));\n        proof = new bytes32[](height);\n        uint256 levelLength = hashes.length;\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Use sibling for the merkle proof; `index^1` is index of our sibling\n                proof[h] = (index ^ 1 \u003c levelLength) ? hashes[index ^ 1] : bytes32(0);\n\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\"\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n                // Traverse to parent node\n                index \u003e\u003e= 1;\n            }\n        }\n    }\n\n    /// @notice Returns the height of the tree having a given amount of leafs.\n    function getHeight(uint256 leafs) internal pure returns (uint256 height) {\n        uint256 amount = 1;\n        while (amount \u003c leafs) {\n            unchecked {\n                ++height;\n            }\n            amount \u003c\u003c= 1;\n        }\n    }\n}\n\n// contracts/libs/stack/GasData.sol\n\n/// GasData in encoded data with \"basic information about gas prices\" for some chain.\ntype GasData is uint96;\n\nusing GasDataLib for GasData global;\n\n/// ChainGas is encoded data with given chain's \"basic information about gas prices\".\ntype ChainGas is uint128;\n\nusing GasDataLib for ChainGas global;\n\n/// Library for encoding and decoding GasData and ChainGas structs.\n/// # GasData\n/// `GasData` is a struct to store the \"basic information about gas prices\", that could\n/// be later used to approximate the cost of a message execution, and thus derive the\n/// minimal tip values for sending a message to the chain.\n/// \u003e - `GasData` is supposed to be cached by `GasOracle` contract, allowing to store the\n/// \u003e approximates instead of the exact values, and thus save on storage costs.\n/// \u003e - For instance, if `GasOracle` only updates the values on +- 10% change, having an\n/// \u003e 0.4% error on the approximates would be acceptable.\n/// `GasData` is supposed to be included in the Origin's state, which are synced across\n/// chains using Agent-signed snapshots and attestations.\n/// ## GasData stack layout (from highest bits to lowest)\n///\n/// | Position   | Field        | Type   | Bytes | Description                                         |\n/// | ---------- | ------------ | ------ | ----- | --------------------------------------------------- |\n/// | (012..010] | gasPrice     | uint16 | 2     | Gas price for the chain (in Wei per gas unit)       |\n/// | (010..008] | dataPrice    | uint16 | 2     | Calldata price (in Wei per byte of content)         |\n/// | (008..006] | execBuffer   | uint16 | 2     | Tx fee safety buffer for message execution (in Wei) |\n/// | (006..004] | amortAttCost | uint16 | 2     | Amortized cost for attestation submission (in Wei)  |\n/// | (004..002] | etherPrice   | uint16 | 2     | Chain's Ether Price / Mainnet Ether Price (in BWAD) |\n/// | (002..000] | markup       | uint16 | 2     | Markup for the message execution (in BWAD)          |\n/// \u003e See Number.sol for more details on `Number` type and BWAD (binary WAD) math.\n///\n/// ## ChainGas stack layout (from highest bits to lowest)\n///\n/// | Position   | Field   | Type   | Bytes | Description      |\n/// | ---------- | ------- | ------ | ----- | ---------------- |\n/// | (016..004] | gasData | uint96 | 12    | Chain's gas data |\n/// | (004..000] | domain  | uint32 | 4     | Chain's domain   |\nlibrary GasDataLib {\n    /// @dev Amount of bits to shift to gasPrice field\n    uint96 private constant SHIFT_GAS_PRICE = 10 * 8;\n    /// @dev Amount of bits to shift to dataPrice field\n    uint96 private constant SHIFT_DATA_PRICE = 8 * 8;\n    /// @dev Amount of bits to shift to execBuffer field\n    uint96 private constant SHIFT_EXEC_BUFFER = 6 * 8;\n    /// @dev Amount of bits to shift to amortAttCost field\n    uint96 private constant SHIFT_AMORT_ATT_COST = 4 * 8;\n    /// @dev Amount of bits to shift to etherPrice field\n    uint96 private constant SHIFT_ETHER_PRICE = 2 * 8;\n\n    /// @dev Amount of bits to shift to gasData field\n    uint128 private constant SHIFT_GAS_DATA = 4 * 8;\n\n    // ═════════════════════════════════════════════════ GAS DATA ══════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded GasData struct with the given fields.\n    /// @param gasPrice_        Gas price for the chain (in Wei per gas unit)\n    /// @param dataPrice_       Calldata price (in Wei per byte of content)\n    /// @param execBuffer_      Tx fee safety buffer for message execution (in Wei)\n    /// @param amortAttCost_    Amortized cost for attestation submission (in Wei)\n    /// @param etherPrice_      Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n    /// @param markup_          Markup for the message execution (in BWAD)\n    function encodeGasData(\n        Number gasPrice_,\n        Number dataPrice_,\n        Number execBuffer_,\n        Number amortAttCost_,\n        Number etherPrice_,\n        Number markup_\n    ) internal pure returns (GasData) {\n        // Number type wraps uint16, so could safely be casted to uint96\n        // forgefmt: disable-next-item\n        return GasData.wrap(\n            uint96(Number.unwrap(gasPrice_)) \u003c\u003c SHIFT_GAS_PRICE |\n            uint96(Number.unwrap(dataPrice_)) \u003c\u003c SHIFT_DATA_PRICE |\n            uint96(Number.unwrap(execBuffer_)) \u003c\u003c SHIFT_EXEC_BUFFER |\n            uint96(Number.unwrap(amortAttCost_)) \u003c\u003c SHIFT_AMORT_ATT_COST |\n            uint96(Number.unwrap(etherPrice_)) \u003c\u003c SHIFT_ETHER_PRICE |\n            uint96(Number.unwrap(markup_))\n        );\n    }\n\n    /// @notice Wraps padded uint256 value into GasData struct.\n    function wrapGasData(uint256 paddedGasData) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(paddedGasData));\n    }\n\n    /// @notice Returns the gas price, in Wei per gas unit.\n    function gasPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_GAS_PRICE));\n    }\n\n    /// @notice Returns the calldata price, in Wei per byte of content.\n    function dataPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_DATA_PRICE));\n    }\n\n    /// @notice Returns the tx fee safety buffer for message execution, in Wei.\n    function execBuffer(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_EXEC_BUFFER));\n    }\n\n    /// @notice Returns the amortized cost for attestation submission, in Wei.\n    function amortAttCost(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_AMORT_ATT_COST));\n    }\n\n    /// @notice Returns the ratio of Chain's Ether Price / Mainnet Ether Price, in BWAD math.\n    function etherPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_ETHER_PRICE));\n    }\n\n    /// @notice Returns the markup for the message execution, in BWAD math.\n    function markup(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data)));\n    }\n\n    // ════════════════════════════════════════════════ CHAIN DATA ═════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded ChainGas struct with the given fields.\n    /// @param gasData_ Chain's gas data\n    /// @param domain_  Chain's domain\n    function encodeChainGas(GasData gasData_, uint32 domain_) internal pure returns (ChainGas) {\n        // GasData type wraps uint96, so could safely be casted to uint128\n        return ChainGas.wrap(uint128(GasData.unwrap(gasData_)) \u003c\u003c SHIFT_GAS_DATA | uint128(domain_));\n    }\n\n    /// @notice Wraps padded uint256 value into ChainGas struct.\n    function wrapChainGas(uint256 paddedChainGas) internal pure returns (ChainGas) {\n        // Casting to uint128 will truncate the highest bits, which is the behavior we want\n        return ChainGas.wrap(uint128(paddedChainGas));\n    }\n\n    /// @notice Returns the chain's gas data.\n    function gasData(ChainGas data) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(ChainGas.unwrap(data) \u003e\u003e SHIFT_GAS_DATA));\n    }\n\n    /// @notice Returns the chain's domain.\n    function domain(ChainGas data) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(ChainGas.unwrap(data));\n    }\n\n    /// @notice Returns the hash for the list of ChainGas structs.\n    function snapGasHash(ChainGas[] memory snapGas) internal pure returns (bytes32 snapGasHash_) {\n        // Use assembly to calculate the hash of the array without copying it\n        // ChainGas takes a single word of storage, thus ChainGas[] is stored in the following way:\n        // 0x00: length of the array, in words\n        // 0x20: first ChainGas struct\n        // 0x40: second ChainGas struct\n        // And so on...\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Find the location where the array data starts, we add 0x20 to skip the length field\n            let loc := add(snapGas, 0x20)\n            // Load the length of the array (in words).\n            // Shifting left 5 bits is equivalent to multiplying by 32: this converts from words to bytes.\n            let len := shl(5, mload(snapGas))\n            // Calculate the hash of the array\n            snapGasHash_ := keccak256(loc, len)\n        }\n    }\n}\n\n// contracts/libs/stack/Header.sol\n\n/// Header is encoded data with \"general routing information\".\ntype Header is uint136;\n\nusing HeaderLib for Header global;\n\n/// Types of messages supported by Origin-Destination\n/// - Base: message sent by protocol user, contains tips\n/// - Manager: message sent between AgentManager contracts located on different chains, no tips\nenum MessageFlag {\n    Base,\n    Manager\n}\n\nusing HeaderLib for MessageFlag global;\n\n/// Library for formatting _the header part_ of _the messages used by Origin and Destination_.\n/// - Header represents general information for routing a Message for Origin and Destination.\n/// - Header occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n///\n/// # Header stack layout (from highest bits to lowest)\n///\n/// | Position   | Field            | Type   | Bytes | Description                             |\n/// | ---------- | ---------------- | ------ | ----- | --------------------------------------- |\n/// | (017..016] | flag             | uint8  | 1     | Flag specifying the type of message     |\n/// | (016..012] | origin           | uint32 | 4     | Domain where message originated         |\n/// | (012..008] | nonce            | uint32 | 4     | Message nonce on the origin domain      |\n/// | (008..004] | destination      | uint32 | 4     | Domain where message will be executed   |\n/// | (004..000] | optimisticPeriod | uint32 | 4     | Optimistic period that will be enforced |\nlibrary HeaderLib {\n    /// @dev Amount of bits to shift to flag field\n    uint136 private constant SHIFT_FLAG = 16 * 8;\n    /// @dev Amount of bits to shift to origin field\n    uint136 private constant SHIFT_ORIGIN = 12 * 8;\n    /// @dev Amount of bits to shift to nonce field\n    uint136 private constant SHIFT_NONCE = 8 * 8;\n    /// @dev Amount of bits to shift to destination field\n    uint136 private constant SHIFT_DESTINATION = 4 * 8;\n\n    /// @notice Returns an encoded header with provided fields\n    /// @param origin_              Domain of origin chain\n    /// @param nonce_               Message nonce on origin chain\n    /// @param destination_         Domain of destination chain\n    /// @param optimisticPeriod_    Optimistic period for message execution\n    function encodeHeader(\n        MessageFlag flag_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint32 destination_,\n        uint32 optimisticPeriod_\n    ) internal pure returns (Header) {\n        // All casts below are upcasts, so they are safe\n        // forgefmt: disable-next-item\n        return Header.wrap(\n            uint136(uint8(flag_)) \u003c\u003c SHIFT_FLAG |\n            uint136(origin_) \u003c\u003c SHIFT_ORIGIN |\n            uint136(nonce_) \u003c\u003c SHIFT_NONCE |\n            uint136(destination_) \u003c\u003c SHIFT_DESTINATION |\n            uint136(optimisticPeriod_)\n        );\n    }\n\n    /// @notice Checks that the header is a valid encoded header.\n    function isHeader(uint256 paddedHeader) internal pure returns (bool) {\n        // Check that flag is within range\n        return _flag(paddedHeader) \u003c= uint8(type(MessageFlag).max);\n    }\n\n    /// @notice Wraps the padded encoded request into a Header-typed value.\n    /// @dev The \"padded\" header is simply an encoded header casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded headers\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedHeader) internal pure returns (Header) {\n        // Check that flag is within range\n        if (!isHeader(paddedHeader)) revert FlagOutOfRange();\n        // Casting to uint136 will truncate the highest bits, which is the behavior we want\n        return Header.wrap(uint136(paddedHeader));\n    }\n\n    /// @notice Returns header's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Header header) internal pure returns (bytes32 hashedHeader) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store header in scratch space\n            mstore(0, header)\n            // Compute hash of header padded to 32 bytes\n            hashedHeader := keccak256(0, 32)\n        }\n    }\n\n    // ══════════════════════════════════════════════ HEADER SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns header's flag field\n    function flag(Header header) internal pure returns (MessageFlag) {\n        // We check that flag is within range when wrapping the header, so this cast is safe\n        return MessageFlag(_flag(Header.unwrap(header)));\n    }\n\n    /// @notice Returns header's origin field\n    function origin(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_ORIGIN);\n    }\n\n    /// @notice Returns header's nonce field\n    function nonce(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_NONCE);\n    }\n\n    /// @notice Returns header's destination field\n    function destination(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_DESTINATION);\n    }\n\n    /// @notice Returns header's optimistic seconds field\n    function optimisticPeriod(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns header's flag field without casting to MessageFlag\n    function _flag(uint256 paddedHeader) private pure returns (uint8) {\n        // Casting to uint8 will truncate the highest bits, which is the behavior we want\n        return uint8(paddedHeader \u003e\u003e SHIFT_FLAG);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n     * constructor.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall \u0026\u0026 _initialized \u003c 1) || (!AddressUpgradeable.isContract(address(this)) \u0026\u0026 _initialized == 1),\n            \"Initializable: contract is already initialized\"\n        );\n        _initialized = 1;\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: setting the version to 255 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing \u0026\u0026 _initialized \u003c version, \"Initializable: contract is already initialized\");\n        _initialized = version;\n        _initializing = true;\n        _;\n        _initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        require(_initializing, \"Initializable: contract is not initializing\");\n        _;\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized != type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint8) {\n        return _initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _initializing;\n    }\n}\n\n// contracts/interfaces/IAgentManager.sol\n\ninterface IAgentManager {\n    /**\n     * @notice Allows Inbox to open a Dispute between a Guard and a Notary, if they are both not in Dispute already.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Guard or Notary is already in Dispute.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Allows Inbox to slash an agent, if their fraud was proven.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Domain doesn't match the saved agent domain.\n     * @param domain    Domain where the Agent is active\n     * @param agent     Address of the Agent\n     * @param prover    Address that initially provided fraud proof\n     */\n    function slashAgent(uint32 domain, address agent, address prover) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest known root of the Agent Merkle Tree.\n     */\n    function agentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns the number of opened Disputes.\n     * @dev This includes the Disputes that have been resolved already.\n     */\n    function getDisputesAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns information about the dispute with the given index.\n     * @dev Will revert if dispute with given index hasn't been opened yet.\n     * @param index             Dispute index\n     * @return guard            Address of the Guard in the Dispute\n     * @return notary           Address of the Notary in the Dispute\n     * @return slashedAgent     Address of the Agent who was slashed when Dispute was resolved\n     * @return fraudProver      Address who provided fraud proof to resolve the Dispute\n     * @return reportPayload    Raw payload with report data that led to the Dispute\n     * @return reportSignature  Guard signature for the report payload\n     */\n    function getDispute(uint256 index)\n        external\n        view\n        returns (\n            address guard,\n            address notary,\n            address slashedAgent,\n            address fraudProver,\n            bytes memory reportPayload,\n            bytes memory reportSignature\n        );\n\n    /**\n     * @notice Returns the current Dispute status of a given agent. See Structures.sol for details.\n     * @dev Every returned value will be set to zero if agent was not slashed and is not in Dispute.\n     * `rival` and `disputePtr` will be set to zero if the agent was slashed without being in Dispute.\n     * @param agent         Agent address\n     * @return flag         Flag describing the current Dispute status for the agent: None/Pending/Slashed\n     * @return rival        Address of the rival agent in the Dispute\n     * @return fraudProver  Address who provided fraud proof to resolve the Dispute\n     * @return disputePtr   Index of the opened Dispute PLUS ONE. Zero if agent is not in Dispute.\n     */\n    function disputeStatus(address agent)\n        external\n        view\n        returns (DisputeFlag flag, address rival, address fraudProver, uint256 disputePtr);\n}\n\n// contracts/interfaces/IAgentSecured.sol\n\ninterface IAgentSecured {\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * between a Guard and a Notary has been opened.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * has been resolved due to one of the agents being slashed.\n     * \u003e `rivalIndex` will be ZERO, if the slashed agent was not in the Dispute.\n     * @param slashedIndex  Index of the slashed agent in the Agent Merkle Tree\n     * @param rivalIndex    Index of the their Dispute Rival in the Agent Merkle Tree\n     */\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the address of the local AgentManager contract, which is treated as\n     * the \"source of truth\" for agent statuses.\n     */\n    function agentManager() external view returns (address);\n\n    /**\n     * @notice Returns the address of the local Inbox contract, which is treated as\n     * the \"source of truth\" for agent-signed statements.\n     * @dev Inbox passes verified agent statements to `IAgentSecured` contract.\n     */\n    function inbox() external view returns (address);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns (flag, openedAt, resolvedAt) that describes the latest status of\n     * the latest dispute for an agent with a given index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param agentIndex    Agent index in the Agent Merkle Tree\n     * @return              Latest dispute status for the given agent: (flag, openedAt, resolvedAt)\n     */\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory);\n}\n\n// contracts/libs/memory/ByteString.sol\n\n/// @dev CallData is a memory view over the payload to be used for an external call, i.e.\n/// recipient.call(callData). Its length is always (4 + 32 * N) bytes:\n/// - First 4 bytes represent the function selector.\n/// - 32 * N bytes represent N words that function arguments occupy.\ntype CallData is uint256;\n\n/// @dev Attach library functions to CallData\nusing ByteString for CallData global;\n\n/// @dev Signature is a memory view over a \"65 bytes\" array representing a ECDSA signature.\ntype Signature is uint256;\n\n/// @dev Attach library functions to Signature\nusing ByteString for Signature global;\n\nlibrary ByteString {\n    using MemViewLib for bytes;\n\n    /**\n     * @dev non-compact ECDSA signatures are enforced as of OZ 4.7.3\n     *\n     *      Signature payload memory layout\n     * [000 .. 032) r   bytes32 32 bytes\n     * [032 .. 064) s   bytes32 32 bytes\n     * [064 .. 065) v   uint8    1 byte\n     */\n    uint256 internal constant SIGNATURE_LENGTH = 65;\n    uint256 private constant OFFSET_R = 0;\n    uint256 private constant OFFSET_S = 32;\n    uint256 private constant OFFSET_V = 64;\n\n    /**\n     * @dev Calldata memory layout\n     * [000 .. 004) selector    bytes4  4 bytes\n     *      Optional: N function arguments\n     * [004 .. 036) arg1        bytes32 32 bytes\n     *      ..\n     * [AAA .. END) argN        bytes32 32 bytes\n     */\n    uint256 internal constant SELECTOR_LENGTH = 4;\n    uint256 private constant OFFSET_SELECTOR = 0;\n    uint256 private constant OFFSET_ARGUMENTS = SELECTOR_LENGTH;\n\n    // ═════════════════════════════════════════════════ SIGNATURE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the signature payload from the given values.\n     * @dev Using ByteString.formatSignature({r: r, s: s, v: v}) will make sure\n     * that params are given in the right order.\n     */\n    function formatSignature(bytes32 r, bytes32 s, uint8 v) internal pure returns (bytes memory) {\n        return abi.encodePacked(r, s, v);\n    }\n\n    /**\n     * @notice Returns a Signature view over for the given payload.\n     * @dev Will revert if the payload is not a signature.\n     */\n    function castToSignature(bytes memory payload) internal pure returns (Signature) {\n        return castToSignature(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Signature view.\n     * @dev Will revert if the memory view is not over a signature.\n     */\n    function castToSignature(MemView memView) internal pure returns (Signature) {\n        if (!isSignature(memView)) revert UnformattedSignature();\n        return Signature.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a signature\n     */\n    function isSignature(MemView memView) internal pure returns (bool) {\n        return memView.len() == SIGNATURE_LENGTH;\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Signature signature) internal pure returns (MemView) {\n        return MemView.wrap(Signature.unwrap(signature));\n    }\n\n    // ═════════════════════════════════════════════ SIGNATURE SLICING ═════════════════════════════════════════════════\n\n    /// @notice Unpacks signature payload into (r, s, v) parameters.\n    /// @dev Make sure to verify signature length with isSignature() beforehand.\n    function toRSV(Signature signature) internal pure returns (bytes32 r, bytes32 s, uint8 v) {\n        // Get the underlying memory view\n        MemView memView = unwrap(signature);\n        r = memView.index({index_: OFFSET_R, bytes_: 32});\n        s = memView.index({index_: OFFSET_S, bytes_: 32});\n        // Can be safely casted to uint8, since we index a single byte\n        v = uint8(memView.indexUint({index_: OFFSET_V, bytes_: 1}));\n    }\n\n    // ═════════════════════════════════════════════════ CALLDATA ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the calldata with the modified arguments:\n     * the existing arguments are prepended with the arguments from the prefix.\n     * @dev Given:\n     *  - `calldata = abi.encodeWithSelector(foo.selector, d, e);`\n     *  - `prefix = abi.encode(a, b, c);`\n     *  - `a`, `b`, `c` are arguments of static type (i.e. not dynamically sized ones)\n     *      Then:\n     *  - Function will return abi.encodeWithSelector(foo.selector, a, c, c, d, e)\n     *  - Returned calldata will trigger `foo(a, b, c, d, e)` when used for a contract call.\n     * Note: for clarification as to what types are considered static, see\n     * https://docs.soliditylang.org/en/latest/abi-spec.html#formal-specification-of-the-encoding\n     * @param callData  Calldata that needs to be modified\n     * @param prefix    ABI-encoded arguments to use as the first arguments in the new calldata\n     * @return Modified calldata having prefix as the first arguments.\n     */\n    function addPrefix(CallData callData, bytes memory prefix) internal view returns (bytes memory) {\n        // Prefix should occupy a whole amount of words in memory\n        if (!_fullWords(prefix.length)) revert UnformattedCallDataPrefix();\n        MemView[] memory views = new MemView[](3);\n        // Use payload's function selector\n        views[0] = abi.encodePacked(callData.callSelector()).ref();\n        // Use prefix as the first arguments\n        views[1] = prefix.ref();\n        // Use payload's remaining arguments\n        views[2] = callData.arguments();\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a CallData view over for the given payload.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(bytes memory payload) internal pure returns (CallData) {\n        return castToCallData(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a CallData view.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(MemView memView) internal pure returns (CallData) {\n        if (!isCallData(memView)) revert UnformattedCallData();\n        return CallData.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a valid calldata, i.e.\n     * a function selector, followed by arbitrary amount of arguments.\n     */\n    function isCallData(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Calldata should at least have a function selector\n        if (length \u003c SELECTOR_LENGTH) return false;\n        // The remainder of the calldata should be exactly N memory words (N \u003e= 0)\n        return _fullWords(length - SELECTOR_LENGTH);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(CallData callData) internal pure returns (MemView) {\n        return MemView.wrap(CallData.unwrap(callData));\n    }\n\n    /// @notice Returns callData's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(CallData callData) internal pure returns (bytes32) {\n        return callData.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ CALLDATA SLICING ══════════════════════════════════════════════════\n\n    /**\n     * @notice Returns amount of memory words (32 byte chunks) the function arguments\n     * occupy in the calldata.\n     * @dev This might differ from amount of arguments supplied, if any of the arguments\n     * occupies more than one memory slot. It is true, however, that argument part of the payload\n     * occupies exactly N words, even for dynamic types like `bytes`\n     */\n    function argumentWords(CallData callData) internal pure returns (uint256) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        // Equivalent of (length - SELECTOR_LENGTH) / 32\n        return (memView.len() - SELECTOR_LENGTH) \u003e\u003e 5;\n    }\n\n    /// @notice Returns selector for the provided calldata.\n    function callSelector(CallData callData) internal pure returns (bytes4) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return bytes4(memView.index({index_: OFFSET_SELECTOR, bytes_: SELECTOR_LENGTH}));\n    }\n\n    /// @notice Returns abi encoded arguments for the provided calldata.\n    function arguments(CallData callData) internal pure returns (MemView) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return memView.sliceFrom({index_: OFFSET_ARGUMENTS});\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if length is full amount of memory words (32 bytes).\n    function _fullWords(uint256 length) internal pure returns (bool) {\n        // The equivalent of length % 32 == 0\n        return length \u0026 31 == 0;\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n    function __Context_init() internal onlyInitializing {\n    }\n\n    function __Context_init_unchained() internal onlyInitializing {\n    }\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[50] private __gap;\n}\n\n// contracts/libs/merkle/MerkleTree.sol\n\n/// `BaseTree` is a struct representing incremental merkle tree.\n/// - Contains only the current branch.\n/// - The number of inserted leaves is stored externally, and is later supplied for tree operations.\n/// - Has a fixed height of `ORIGIN_TREE_HEIGHT`.\n/// - Can store up to `2 ** ORIGIN_TREE_HEIGHT - 1` leaves.\n/// \u003e Note: the hash function for the tree `H(x, y)` is defined as:\n/// \u003e - `H(0,0) = 0`\n/// \u003e - `H(x,y) = keccak256(x, y), when (x != 0 || y != 0)`\n/// ## Invariant for leafs\n/// - The leftmost empty leaf has `index == count`, where `count` is the amount of the inserted leafs so far.\n/// - Value for any empty leaf or node is bytes32(0).\n/// ## Invariant for current branch\n/// `branch[i]` is always the value of a node on the i-th level.\n/// Levels are numbered from leafs to root: `0 .. ORIGIN_TREE_HEIGHT`.\n/// `branch[i]` stores the value for the node, such that:\n//  - The node is a \"left child\" (e.g. has an even index).\n/// - The node must have two non-empty children.\n/// - Out of all level's \"left child\" nodes with \"non-empty children\",\n/// the one with the biggest index (the rightmost one) is stored as `branch[i]`.\n/// \u003e __`branch` could be used to form a proof of inclusion for the first empty leaf (`index == count`).__\n/// _Here is how:_\n/// - Let's walk along the path from the \"first empty leaf\" to the root.\n/// - i-th bit of the \"first empty leaf\" index (which is equal to `count`) determines if the path's node\n/// for this i-th level is a \"left child\" or a \"right child\".\n/// - i-th bit in `count` is 0 → we are the left child on this level → sibling is the right child\n/// that does not exist yet → `proof[i] = bytes32(0)`.\n/// - i-th bit in `count` is 1 → we are the right child on this level → sibling is the left child\n/// sibling is the rightmost \"left child\" node on the level → `proof[i] = branch[i]`.\n/// \u003e Therefore `proof[i] = (count \u0026 (1 \u003c\u003c i)) == 0 ? bytes32(0) : branch[i])`\nstruct BaseTree {\n    bytes32[ORIGIN_TREE_HEIGHT] branch;\n}\n\nusing MerkleTree for BaseTree global;\n\n/// `HistoricalTree` is an incremental merkle tree keeping track of its historical merkle roots.\n/// \u003e - `roots[N]` is the root of the tree after `N` leafs were inserted\n/// \u003e - `roots[0] == bytes32(0)`\n/// @param tree     Incremental merkle tree\n/// @param roots    Historical merkle roots of the tree\nstruct HistoricalTree {\n    BaseTree tree;\n    bytes32[] roots;\n}\n\nusing MerkleTree for HistoricalTree global;\n\n/// `DynamicTree` is a struct representing a Merkle Tree with `2**AGENT_TREE_HEIGHT` leaves.\n/// - A single operation is available: update value for leaf with an arbitrary index (which might be a non-empty leaf).\n/// - This is done by requesting the proof of inclusion for the old value, which is used to both\n/// verify the old value, and calculate the new root.\n/// \u003e Based on Original idea from [ER forum post](https://ethresear.ch/t/efficient-on-chain-dynamic-merkle-tree/11054).\nstruct DynamicTree {\n    bytes32 root;\n}\n\nusing MerkleTree for DynamicTree global;\n\n/// MerkleTree is work based on Nomad's Merkle.sol, which is used under MIT OR Apache-2.0\n/// [link](https://github.com/nomad-xyz/monorepo/blob/main/packages/contracts-core/contracts/libs/Merkle.sol).\n/// With the following changes:\n/// - Adapted for Solidity 0.8.x.\n/// - Amount of tree leaves stored externally.\n/// - Added thorough documentation.\n/// - `H(0,0) = 0` optimization from [ER forum post](https://ethresear.ch/t/optimizing-sparse-merkle-trees/3751/6).\n/// \u003e Nomad's Merkle.sol is work based on eth2 deposit contract, which is used under CC0-1.0\n///[link](https://github.com/ethereum/deposit_contract/blob/dev/deposit_contract/contracts/validator_registration.v.py).\n/// With the following changes:\n/// \u003e - Implemented in Solidity 0.7.6 (eth2 deposit contract implemented in Vyper).\n/// \u003e - `H() = keccak256()` is used as the hashing function instead of `sha256()`.\nlibrary MerkleTree {\n    /// @dev For root calculation we need at least one empty leaf, thus the minus one in the formula.\n    uint256 internal constant MAX_LEAVES = 2 ** ORIGIN_TREE_HEIGHT - 1;\n\n    // ═════════════════════════════════════════════════ BASE TREE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Inserts `node` into merkle tree\n     * @dev Reverts if tree is full\n     * @param newCount  Amount of inserted leaves in the tree after the insertion (i.e. current + 1)\n     * @param node      Element to insert into tree\n     */\n    function insertBase(BaseTree storage tree, uint256 newCount, bytes32 node) internal {\n        if (newCount \u003e MAX_LEAVES) revert MerkleTreeFull();\n        // We go up the tree following the branch from the empty leaf AFTER the just inserted one.\n        // We stop when we find the first \"right child\" node.\n        // Its sibling is now the rightmost \"left child\" node that has two non-empty children.\n        // Therefore we need to update `tree.branch` value on this level.\n        // One could see that `tree.branch` value on lower and higher levels remain unchanged.\n\n        // Loop invariant: `node` is the current level's value for the branch from JUST INSERTED leaf\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            if ((newCount \u0026 1) == 1) {\n                // Found the first \"right child\" node on the branch from EMPTY leaf\n                // `node` is the value for node on branch from JUST INSERTED leaf\n                // Which in this case is the \"left child\".\n                // We update tree.branch and exit\n                tree.branch[i] = node;\n                return;\n            }\n            // On the branch from EMPTY leaf this is still a \"left child\".\n            // Meaning on branch from JUST INSERTED leaf, `node` is a right child.\n            // We compute value for `node` parent using `tree.branch` invariant:\n            // This is the rightmost \"left child\" node, which would be sibling of `node`.\n            node = MerkleMath.getParent(tree.branch[i], node);\n            // Get the parent index, and go to the next tree level\n            newCount \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n        // As the loop should always end prematurely with the `return` statement,\n        // this code should be unreachable. We assert `false` just to be safe.\n        assert(false);\n    }\n\n    /**\n     * @notice Calculates and returns current root of the merkle tree.\n     * @param count     Current amount of inserted leaves in the tree\n     * @return current  Calculated root of `tree`\n     */\n    function rootBase(BaseTree storage tree, uint256 count) internal view returns (bytes32 current) {\n        // To calculate the root we follow the branch of first EMPTY leaf (index == count)\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            // Check if we are the left or the right child on the current level\n            if ((count \u0026 1) == 1) {\n                // We are the right child. Our sibling is the \"rightmost\" \"left-child\" node\n                // that has two non-empty children → sibling is `tree.branch[i]`\n                current = MerkleMath.getParent(tree.branch[i], current);\n            } else {\n                // We are the left child. Our sibling does not exist yet → sibling is EMPTY\n                current = MerkleMath.getParent(current, bytes32(0));\n            }\n            // Get the parent index, and go to the next tree level\n            count \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    // ══════════════════════════════════════════════ HISTORICAL TREE ══════════════════════════════════════════════════\n\n    /// @notice Initializes the historical roots for the tree by inserting an empty root.\n    // solhint-disable-next-line ordering\n    function initializeRoots(HistoricalTree storage tree) internal returns (bytes32 savedRoot) {\n        // This should only be called once, when the contract is initialized\n        assert(tree.roots.length == 0);\n        // Save root for empty merkle tree: bytes32(0)\n        tree.roots.push(savedRoot);\n    }\n\n    /// @notice Inserts a new leaf into the merkle tree.\n    /// @dev Reverts if tree is full.\n    /// @param node         Element to insert into tree\n    /// @return newRoot     Merkle root after the leaf was inserted\n    function insert(HistoricalTree storage tree, bytes32 node) internal returns (bytes32 newRoot) {\n        // Tree count after the new leaf will be inserted (we store roots[0] as root of empty tree)\n        uint256 newCount = tree.roots.length;\n        tree.tree.insertBase(newCount, node);\n        // Save the new root\n        newRoot = tree.tree.rootBase(newCount);\n        tree.roots.push(newRoot);\n    }\n\n    /// @notice Returns the historical root of the merkle tree.\n    /// @dev Reverts if not enough leafs have been inserted.\n    /// @param count            Amount of leafs in the tree at some point of time\n    /// @return historicalRoot  Merkle root after `count` leafs were inserted\n    function root(HistoricalTree storage tree, uint256 count) internal view returns (bytes32 historicalRoot) {\n        if (count \u003e= tree.roots.length) revert NotEnoughLeafs();\n        return tree.roots[count];\n    }\n\n    // ═══════════════════════════════════════════════ DYNAMIC TREE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Updates the value for the leaf with the given index in the Dynamic Merkle Tree.\n     * @dev Will revert if incorrect proof of inclusion for old value is supplied.\n     * @param tree          Dynamic merkle tree\n     * @param index         Index of the leaf to update\n     * @param oldValue      Previous value of the leaf\n     * @param branch        Proof of inclusion of previous value into the tree\n     * @param newValue      New leaf value to assign\n     * @return newRoot      New value for the Merkle Root after the leaf is updated\n     */\n    function update(\n        DynamicTree storage tree,\n        uint256 index,\n        bytes32 oldValue,\n        bytes32[] memory branch,\n        bytes32 newValue\n    ) internal returns (bytes32 newRoot) {\n        // Check that the old value + proof result in a correct root\n        if (MerkleMath.proofRoot(index, oldValue, branch, AGENT_TREE_HEIGHT) != tree.root) {\n            revert LeafNotProven();\n        }\n        // New root is new value + the same proof (values for sibling nodes are not updated)\n        newRoot = MerkleMath.proofRoot(index, newValue, branch, AGENT_TREE_HEIGHT);\n        // Write the new root\n        tree.root = newRoot;\n    }\n}\n\n// contracts/libs/stack/Tips.sol\n\n/// Tips is encoded data with \"tips paid for sending a base message\".\n/// Note: even though uint256 is also an underlying type for MemView, Tips is stored ON STACK.\ntype Tips is uint256;\n\nusing TipsLib for Tips global;\n\n/// # Tips\n/// Library for formatting _the tips part_ of _the base messages_.\n///\n/// ## How the tips are awarded\n/// Tips are paid for sending a base message, and are split across all the agents that\n/// made the message execution on destination chain possible.\n/// ### Summit tips\n/// Split between:\n///     - Guard posting a snapshot with state ST_G for the origin chain.\n///     - Notary posting a snapshot SN_N using ST_G. This creates attestation A.\n///     - Notary posting a message receipt after it is executed on destination chain.\n/// ### Attestation tips\n/// Paid to:\n///     - Notary posting attestation A to destination chain.\n/// ### Execution tips\n/// Paid to:\n///     - First executor performing a valid execution attempt (correct proofs, optimistic period over),\n///      using attestation A to prove message inclusion on origin chain, whether the recipient reverted or not.\n/// ### Delivery tips.\n/// Paid to:\n///     - Executor who successfully executed the message on destination chain.\n///\n/// ## Tips encoding\n/// - Tips occupy a single storage word, and thus are stored on stack instead of being stored in memory.\n/// - The actual tip values should be determined by multiplying stored values by divided by TIPS_MULTIPLIER=2**32.\n/// - Tips are packed into a single word of storage, while allowing real values up to ~8*10**28 for every tip category.\n/// \u003e The only downside is that the \"real tip values\" are now multiplies of ~4*10**9, which should be fine even for\n/// the chains with the most expensive gas currency.\n/// # Tips stack layout (from highest bits to lowest)\n///\n/// | Position   | Field          | Type   | Bytes | Description                                                |\n/// | ---------- | -------------- | ------ | ----- | ---------------------------------------------------------- |\n/// | (032..024] | summitTip      | uint64 | 8     | Tip for agents interacting with Summit contract            |\n/// | (024..016] | attestationTip | uint64 | 8     | Tip for Notary posting attestation to Destination contract |\n/// | (016..008] | executionTip   | uint64 | 8     | Tip for valid execution attempt on destination chain       |\n/// | (008..000] | deliveryTip    | uint64 | 8     | Tip for successful message delivery on destination chain   |\n\nlibrary TipsLib {\n    using SafeCast for uint256;\n\n    /// @dev Amount of bits to shift to summitTip field\n    uint256 private constant SHIFT_SUMMIT_TIP = 24 * 8;\n    /// @dev Amount of bits to shift to attestationTip field\n    uint256 private constant SHIFT_ATTESTATION_TIP = 16 * 8;\n    /// @dev Amount of bits to shift to executionTip field\n    uint256 private constant SHIFT_EXECUTION_TIP = 8 * 8;\n\n    // ═══════════════════════════════════════════════════ TIPS ════════════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips with the given fields\n    /// @param summitTip_        Tip for agents interacting with Summit contract, divided by TIPS_MULTIPLIER\n    /// @param attestationTip_   Tip for Notary posting attestation to Destination contract, divided by TIPS_MULTIPLIER\n    /// @param executionTip_     Tip for valid execution attempt on destination chain, divided by TIPS_MULTIPLIER\n    /// @param deliveryTip_      Tip for successful message delivery on destination chain, divided by TIPS_MULTIPLIER\n    function encodeTips(uint64 summitTip_, uint64 attestationTip_, uint64 executionTip_, uint64 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // forgefmt: disable-next-item\n        return Tips.wrap(\n            uint256(summitTip_) \u003c\u003c SHIFT_SUMMIT_TIP |\n            uint256(attestationTip_) \u003c\u003c SHIFT_ATTESTATION_TIP |\n            uint256(executionTip_) \u003c\u003c SHIFT_EXECUTION_TIP |\n            uint256(deliveryTip_)\n        );\n    }\n\n    /// @notice Convenience function to encode tips with uint256 values.\n    function encodeTips256(uint256 summitTip_, uint256 attestationTip_, uint256 executionTip_, uint256 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // In practice, the tips amounts are not supposed to be higher than 2**96, and with 32 bits of granularity\n        // using uint64 is enough to store the values. However, we still check for overflow just in case.\n        // TODO: consider using Number type to store the tips values.\n        return encodeTips({\n            summitTip_: (summitTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            attestationTip_: (attestationTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            executionTip_: (executionTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            deliveryTip_: (deliveryTip_ \u003e\u003e TIPS_GRANULARITY).toUint64()\n        });\n    }\n\n    /// @notice Wraps the padded encoded tips into a Tips-typed value.\n    /// @dev There is no actual padding here, as the underlying type is already uint256,\n    /// but we include this function for consistency and to be future-proof, if tips will eventually use anything\n    /// smaller than uint256.\n    function wrapPadded(uint256 paddedTips) internal pure returns (Tips) {\n        return Tips.wrap(paddedTips);\n    }\n\n    /**\n     * @notice Returns a formatted Tips payload specifying empty tips.\n     * @return Formatted tips\n     */\n    function emptyTips() internal pure returns (Tips) {\n        return Tips.wrap(0);\n    }\n\n    /// @notice Returns tips's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Tips tips) internal pure returns (bytes32 hashedTips) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store tips in scratch space\n            mstore(0, tips)\n            // Compute hash of tips padded to 32 bytes\n            hashedTips := keccak256(0, 32)\n        }\n    }\n\n    // ═══════════════════════════════════════════════ TIPS SLICING ════════════════════════════════════════════════════\n\n    /// @notice Returns summitTip field\n    function summitTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_SUMMIT_TIP);\n    }\n\n    /// @notice Returns attestationTip field\n    function attestationTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_ATTESTATION_TIP);\n    }\n\n    /// @notice Returns executionTip field\n    function executionTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_EXECUTION_TIP);\n    }\n\n    /// @notice Returns deliveryTip field\n    function deliveryTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips));\n    }\n\n    // ════════════════════════════════════════════════ TIPS VALUE ═════════════════════════════════════════════════════\n\n    /// @notice Returns total value of the tips payload.\n    /// This is the sum of the encoded values, scaled up by TIPS_MULTIPLIER\n    function value(Tips tips) internal pure returns (uint256 value_) {\n        value_ = uint256(tips.summitTip()) + tips.attestationTip() + tips.executionTip() + tips.deliveryTip();\n        value_ \u003c\u003c= TIPS_GRANULARITY;\n    }\n\n    /// @notice Increases the delivery tip to match the new value.\n    function matchValue(Tips tips, uint256 newValue) internal pure returns (Tips newTips) {\n        uint256 oldValue = tips.value();\n        if (newValue \u003c oldValue) revert TipsValueTooLow();\n        // We want to increase the delivery tip, while keeping the other tips the same\n        unchecked {\n            uint256 delta = (newValue - oldValue) \u003e\u003e TIPS_GRANULARITY;\n            // `delta` fits into uint224, as TIPS_GRANULARITY is 32, so this never overflows uint256.\n            // In practice, this will never overflow uint64 as well, but we still check it just in case.\n            if (delta + tips.deliveryTip() \u003e type(uint64).max) revert TipsOverflow();\n            // Delivery tips occupy lowest 8 bytes, so we can just add delta to the tips value\n            // to effectively increase the delivery tip (knowing that delta fits into uint64).\n            newTips = Tips.wrap(Tips.unwrap(tips) + delta);\n        }\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    function __Ownable_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable_init_unchained() internal onlyInitializing {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n    function __Ownable2Step_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable2Step_init_unchained() internal onlyInitializing {\n    }\n    address private _pendingOwner;\n\n    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Returns the address of the pending owner.\n     */\n    function pendingOwner() public view virtual returns (address) {\n        return _pendingOwner;\n    }\n\n    /**\n     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual override onlyOwner {\n        _pendingOwner = newOwner;\n        emit OwnershipTransferStarted(owner(), newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual override {\n        delete _pendingOwner;\n        super._transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev The new owner accepts the ownership transfer.\n     */\n    function acceptOwnership() public virtual {\n        address sender = _msgSender();\n        require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n        _transferOwnership(sender);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// contracts/libs/memory/State.sol\n\n/// State is a memory view over a formatted state payload.\ntype State is uint256;\n\nusing StateLib for State global;\n\n/// # State\n/// State structure represents the state of Origin contract at some point of time.\n/// - State is structured in a way to track the updates of the Origin Merkle Tree.\n/// - State includes root of the Origin Merkle Tree, origin domain and some additional metadata.\n/// ## Origin Merkle Tree\n/// Hash of every sent message is inserted in the Origin Merkle Tree, which changes\n/// the value of Origin Merkle Root (which is the root for the mentioned tree).\n/// - Origin has a single Merkle Tree for all messages, regardless of their destination domain.\n/// - This leads to Origin state being updated if and only if a message was sent in a block.\n/// - Origin contract is a \"source of truth\" for states: a state is considered \"valid\" in its Origin,\n/// if it matches the state of the Origin contract after the N-th (nonce) message was sent.\n///\n/// # Memory layout of State fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                    |\n/// | ---------- | ----------- | ------- | ----- | ------------------------------ |\n/// | [000..032) | root        | bytes32 | 32    | Root of the Origin Merkle Tree |\n/// | [032..036) | origin      | uint32  | 4     | Domain where Origin is located |\n/// | [036..040) | nonce       | uint32  | 4     | Amount of sent messages        |\n/// | [040..045) | blockNumber | uint40  | 5     | Block of last sent message     |\n/// | [045..050) | timestamp   | uint40  | 5     | Time of last sent message      |\n/// | [050..062) | gasData     | uint96  | 12    | Gas data for the chain         |\n///\n/// @dev State could be used to form a Snapshot to be signed by a Guard or a Notary.\nlibrary StateLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_ROOT = 0;\n    uint256 private constant OFFSET_ORIGIN = 32;\n    uint256 private constant OFFSET_NONCE = 36;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 40;\n    uint256 private constant OFFSET_TIMESTAMP = 45;\n    uint256 private constant OFFSET_GAS_DATA = 50;\n\n    // ═══════════════════════════════════════════════════ STATE ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted State payload with provided fields\n     * @param root_         New merkle root\n     * @param origin_       Domain of Origin's chain\n     * @param nonce_        Nonce of the merkle root\n     * @param blockNumber_  Block number when root was saved in Origin\n     * @param timestamp_    Block timestamp when root was saved in Origin\n     * @param gasData_      Gas data for the chain\n     * @return Formatted state\n     */\n    function formatState(\n        bytes32 root_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_,\n        GasData gasData_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(root_, origin_, nonce_, blockNumber_, timestamp_, gasData_);\n    }\n\n    /**\n     * @notice Returns a State view over the given payload.\n     * @dev Will revert if the payload is not a state.\n     */\n    function castToState(bytes memory payload) internal pure returns (State) {\n        return castToState(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a State view.\n     * @dev Will revert if the memory view is not over a state.\n     */\n    function castToState(MemView memView) internal pure returns (State) {\n        if (!isState(memView)) revert UnformattedState();\n        return State.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted State.\n    function isState(MemView memView) internal pure returns (bool) {\n        return memView.len() == STATE_LENGTH;\n    }\n\n    /// @notice Returns the hash of a State, that could be later signed by a Guard to signal\n    /// that the state is invalid.\n    function hashInvalid(State state) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(stateInvalidSalt, keccak(state))\n        return state.unwrap().keccakSalted(STATE_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(State state) internal pure returns (MemView) {\n        return MemView.wrap(State.unwrap(state));\n    }\n\n    /// @notice Compares two State structures.\n    function equals(State a, State b) internal pure returns (bool) {\n        // Length of a State payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═══════════════════════════════════════════════ STATE HASHING ═══════════════════════════════════════════════════\n\n    /// @notice Returns the hash of the State.\n    /// @dev We are using the Merkle Root of a tree with two leafs (see below) as state hash.\n    function leaf(State state) internal pure returns (bytes32) {\n        (bytes32 leftLeaf_, bytes32 rightLeaf_) = state.subLeafs();\n        // Final hash is the parent of these leafs\n        return keccak256(bytes.concat(leftLeaf_, rightLeaf_));\n    }\n\n    /// @notice Returns \"sub-leafs\" of the State. Hash of these \"sub leafs\" is going to be used\n    /// as a \"state leaf\" in the \"Snapshot Merkle Tree\".\n    /// This enables proving that leftLeaf = (root, origin) was a part of the \"Snapshot Merkle Tree\",\n    /// by combining `rightLeaf` with the remainder of the \"Snapshot Merkle Proof\".\n    function subLeafs(State state) internal pure returns (bytes32 leftLeaf_, bytes32 rightLeaf_) {\n        MemView memView = state.unwrap();\n        // Left leaf is (root, origin)\n        leftLeaf_ = memView.prefix({len_: OFFSET_NONCE}).keccak();\n        // Right leaf is (metadata), or (nonce, blockNumber, timestamp)\n        rightLeaf_ = memView.sliceFrom({index_: OFFSET_NONCE}).keccak();\n    }\n\n    /// @notice Returns the left \"sub-leaf\" of the State.\n    function leftLeaf(bytes32 root_, uint32 origin_) internal pure returns (bytes32) {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(root_, origin_));\n    }\n\n    /// @notice Returns the right \"sub-leaf\" of the State.\n    function rightLeaf(uint32 nonce_, uint40 blockNumber_, uint40 timestamp_, GasData gasData_)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(nonce_, blockNumber_, timestamp_, gasData_));\n    }\n\n    // ═══════════════════════════════════════════════ STATE SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns a historical Merkle root from the Origin contract.\n    function root(State state) internal pure returns (bytes32) {\n        return state.unwrap().index({index_: OFFSET_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns domain of chain where the Origin contract is deployed.\n    function origin(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns nonce of Origin contract at the time, when `root` was the Merkle root.\n    function nonce(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when `root` was saved in Origin.\n    function blockNumber(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when `root` was saved in Origin.\n    /// @dev This is the timestamp according to the origin chain.\n    function timestamp(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n\n    /// @notice Returns gas data for the chain.\n    function gasData(State state) internal pure returns (GasData) {\n        return GasDataLib.wrapGasData(state.unwrap().indexUint({index_: OFFSET_GAS_DATA, bytes_: GAS_DATA_LENGTH}));\n    }\n}\n\n// contracts/libs/memory/BaseMessage.sol\n\n/// BaseMessage is a memory view over the base message supported by Origin-Destination\ntype BaseMessage is uint256;\n\nusing BaseMessageLib for BaseMessage global;\n\n/// BaseMessage structure represents a base message sent via the Origin-Destination contracts.\n/// - It only contains data relevant to the base message, the rest of data is encoded in the message header.\n/// - `sender` and `recipient` for EVM chains are EVM addresses casted to bytes32, while preserving left-alignment.\n/// - `tips` and `request` parameters are specified by a message sender\n/// \u003e Origin will calculate minimum tips for given request and content length, and will reject messages with tips\n/// lower than that.\n///\n/// # Memory layout of BaseMessage fields\n///\n/// | Position   | Field     | Type    | Bytes | Description                            |\n/// | ---------- | --------- | ------- | ----- | -------------------------------------- |\n/// | [000..032) | tips      | uint256 | 32    | Encoded tips paid on origin chain      |\n/// | [032..064) | sender    | bytes32 | 32    | Sender address on origin chain         |\n/// | [064..096) | recipient | bytes32 | 32    | Recipient address on destination chain |\n/// | [096..116) | request   | uint160 | 20    | Encoded request for message execution  |\n/// | [104..AAA) | content   | bytes   | ??    | Content to be passed to recipient      |\nlibrary BaseMessageLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_TIPS = 0;\n    uint256 private constant OFFSET_SENDER = 32;\n    uint256 private constant OFFSET_RECIPIENT = 64;\n    uint256 private constant OFFSET_REQUEST = OFFSET_RECIPIENT + TIPS_LENGTH;\n    uint256 private constant OFFSET_CONTENT = OFFSET_REQUEST + REQUEST_LENGTH;\n\n    // ═══════════════════════════════════════════════ BASE MESSAGE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted BaseMessage payload with provided fields.\n     * @param tips_         Encoded tips information\n     * @param sender_       Sender address on origin chain\n     * @param recipient_    Recipient address on destination chain\n     * @param request_      Encoded request for message execution\n     * @param content_      Raw content to be passed to recipient on destination chain\n     * @return Formatted base message\n     */\n    function formatBaseMessage(Tips tips_, bytes32 sender_, bytes32 recipient_, Request request_, bytes memory content_)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return abi.encodePacked(tips_, sender_, recipient_, request_, content_);\n    }\n\n    /**\n     * @notice Returns a BaseMessage view over the given payload.\n     * @dev Will revert if the payload is not a base message.\n     */\n    function castToBaseMessage(bytes memory payload) internal pure returns (BaseMessage) {\n        return castToBaseMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a BaseMessage view.\n     * @dev Will revert if the memory view is not over a base message payload.\n     */\n    function castToBaseMessage(MemView memView) internal pure returns (BaseMessage) {\n        if (!isBaseMessage(memView)) revert UnformattedBaseMessage();\n        return BaseMessage.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted BaseMessage.\n    function isBaseMessage(MemView memView) internal pure returns (bool) {\n        // Check if sender, recipient, tips fields exist\n        return (memView.len() \u003e= OFFSET_CONTENT);\n        // Content could be empty, so we don't check that\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(BaseMessage baseMessage) internal pure returns (MemView) {\n        return MemView.wrap(BaseMessage.unwrap(baseMessage));\n    }\n\n    /// @notice Returns baseMessage's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        // We hash \"tips\" and \"everything but tips\" to make tips proofs easier to verify\n        return MerkleMath.getParent(baseMessage.tips().leaf(), baseMessage.bodyLeaf());\n    }\n\n    /// @notice Returns hash for the \"everything but tips\" part of the base message.\n    function bodyLeaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_SENDER}).keccak();\n    }\n\n    // ═══════════════════════════════════════════ BASE MESSAGE SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips paid on origin chain.\n    function tips(BaseMessage baseMessage) internal pure returns (Tips) {\n        return TipsLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_TIPS, bytes_: TIPS_LENGTH})));\n    }\n\n    /// @notice Returns sender address on origin chain.\n    function sender(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_SENDER, bytes_: 32});\n    }\n\n    /// @notice Returns recipient address on destination chain.\n    function recipient(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_RECIPIENT, bytes_: 32});\n    }\n\n    /// @notice Returns an encoded request for message execution on destination chain.\n    function request(BaseMessage baseMessage) internal pure returns (Request) {\n        return RequestLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_REQUEST, bytes_: REQUEST_LENGTH})));\n    }\n\n    /// @notice Returns an untyped memory view over the content to be passed to recipient.\n    function content(BaseMessage baseMessage) internal pure returns (MemView) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_CONTENT});\n    }\n}\n\n// contracts/base/MessagingBase.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for all messaging contracts.\n * - Provides context on the local chain's domain.\n * - Provides ownership functionality.\n * - Will be providing pausing functionality when it is implemented.\n */\nabstract contract MessagingBase is MultiCallable, Versioned, Ownable2StepUpgradeable {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @notice Domain of the local chain, set once upon contract creation\n    uint32 public immutable localDomain;\n    // @notice Domain of the Synapse chain, set once upon contract creation\n    uint32 public immutable synapseDomain;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev gap for upgrade safety\n    uint256[50] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    constructor(string memory version_, uint32 synapseDomain_) Versioned(version_) {\n        localDomain = ChainContext.chainId();\n        synapseDomain = synapseDomain_;\n    }\n\n    // TODO: Implement pausing\n\n    /**\n     * @dev Should be impossible to renounce ownership;\n     * we override OpenZeppelin OwnableUpgradeable's\n     * implementation of renounceOwnership to make it a no-op\n     */\n    function renounceOwnership() public override onlyOwner {} //solhint-disable-line no-empty-blocks\n}\n\n// contracts/libs/memory/Message.sol\n\n/// Message is a memory over over a formatted message payload.\ntype Message is uint256;\n\nusing MessageLib for Message global;\n\n/// Library for formatting the various messages supported by Origin and Destination.\n///\n/// # Message memory layout\n///\n/// | Position   | Field  | Type    | Bytes | Description                                             |\n/// | ---------- | ------ | ------- | ----- | ------------------------------------------------------- |\n/// | [000..017) | header | uint136 | 17    | Encoded general routing information for the message     |\n/// | [017..AAA) | body   | bytes   | ??    | Formatted payload (according to flag) with message body |\nlibrary MessageLib {\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MemViewLib for bytes;\n    using HeaderLib for MemView;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_HEADER = 0;\n    uint256 private constant OFFSET_BODY = OFFSET_HEADER + HEADER_LENGTH;\n\n    // ══════════════════════════════════════════════════ MESSAGE ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns formatted message with provided fields.\n     * @param header_   Encoded general routing information for the message\n     * @param body_     Formatted payload (according to flag) with message body\n     * @return Formatted message\n     */\n    function formatMessage(Header header_, bytes memory body_) internal pure returns (bytes memory) {\n        return abi.encodePacked(header_, body_);\n    }\n\n    /**\n     * @notice Returns a Message view over for the given payload.\n     * @dev Will revert if the payload is not a message payload.\n     */\n    function castToMessage(bytes memory payload) internal pure returns (Message) {\n        return castToMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Message view.\n     * @dev Will revert if the memory view is not over a message payload.\n     */\n    function castToMessage(MemView memView) internal pure returns (Message) {\n        if (!isMessage(memView)) revert UnformattedMessage();\n        return Message.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Message.\n     */\n    function isMessage(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Check if headers exist in the payload\n        if (length \u003c OFFSET_BODY) return false;\n        // Check that Header is valid\n        uint256 paddedHeader = _header(memView);\n        if (!HeaderLib.isHeader(paddedHeader)) return false;\n        // Check that body is formatted according to the flag\n        // Only Base/Manager message flags exist\n        if (HeaderLib.wrapPadded(paddedHeader).flag() == MessageFlag.Base) {\n            // Check if body is a formatted base message\n            return _body(memView).isBaseMessage();\n        } else {\n            // Check if body is a formatted calldata for AgentManager call\n            return _body(memView).isCallData();\n        }\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Message message) internal pure returns (MemView) {\n        return MemView.wrap(Message.unwrap(message));\n    }\n\n    /// @notice Returns message's hash: a leaf to be inserted in the Merkle tree.\n    function leaf(Message message) internal pure returns (bytes32) {\n        // We hash header and body separately to make message proofs easier to verify\n        Header header_ = message.header();\n        // Only Base/Manager message flags exist\n        if (header_.flag() == MessageFlag.Base) {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToBaseMessage().leaf());\n        } else {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToCallData().leaf());\n        }\n    }\n\n    // ══════════════════════════════════════════════ MESSAGE SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns message's encoded header field.\n    function header(Message message) internal pure returns (Header) {\n        return HeaderLib.wrapPadded((message.unwrap().indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH})));\n    }\n\n    /// @notice Returns message's body field as an untyped memory view.\n    function body(Message message) internal pure returns (MemView) {\n        MemView memView = message.unwrap();\n        return _body(memView);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns message's padded header without checking that it is a valid header.\n    function _header(MemView memView) private pure returns (uint256) {\n        return memView.indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH});\n    }\n\n    /// @dev Returns an untyped memory view over the body field without checking\n    /// if the whole payload or the body are properly formatted.\n    function _body(MemView memView) private pure returns (MemView) {\n        return memView.sliceFrom({index_: OFFSET_BODY});\n    }\n}\n\n// contracts/base/AgentSecured.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for messaging contracts that are secured by the agent manager.\n * `AgentSecured` relies on `AgentManager` to provide the following functionality:\n * - Keep track of agents and their statuses.\n * - Pass agent-signed statements that were verified by the agent manager.\n * - These statements are considered valid indefinitely, unless the agent is disputed.\n * - Disputes are opened and resolved by the agent manager.\n * \u003e `AgentSecured` implementation should never use statements signed by agents that are disputed.\n */\nabstract contract AgentSecured is MessagingBase, IAgentSecured {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    address public immutable agentManager;\n\n    /// @inheritdoc IAgentSecured\n    address public immutable inbox;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    // (agent index =\u003e their dispute status: flag, openedAt, resolvedAt)\n    mapping(uint32 =\u003e DisputeStatus) internal _disputes;\n\n    /// @dev gap for upgrade safety\n    uint256[49] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    modifier onlyAgentManager() {\n        if (msg.sender != agentManager) revert CallerNotAgentManager();\n        _;\n    }\n\n    modifier onlyInbox() {\n        if (msg.sender != inbox) revert CallerNotInbox();\n        _;\n    }\n\n    constructor(string memory version_, uint32 synapseDomain_, address agentManager_, address inbox_)\n        MessagingBase(version_, synapseDomain_)\n    {\n        agentManager = agentManager_;\n        inbox = inbox_;\n    }\n\n    // ════════════════════════════════════════════ ONLY AGENT MANAGER ═════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external onlyAgentManager {\n        uint40 openedAt = ChainContext.blockTimestamp();\n        DisputeStatus memory status = DisputeStatus({flag: DisputeFlag.Pending, openedAt: openedAt, resolvedAt: 0});\n        _disputes[guardIndex] = status;\n        _disputes[notaryIndex] = status;\n    }\n\n    /// @inheritdoc IAgentSecured\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external onlyAgentManager {\n        // Update the dispute status of the slashed agent first.\n        uint40 resolvedAt = ChainContext.blockTimestamp();\n        _disputes[slashedIndex].flag = DisputeFlag.Slashed;\n        _disputes[slashedIndex].resolvedAt = resolvedAt;\n        // Mark the rival agent as not disputed, if there was an ongoing dispute.\n        if (rivalIndex != 0) {\n            _disputes[rivalIndex].flag = DisputeFlag.None;\n            _disputes[rivalIndex].resolvedAt = resolvedAt;\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function agentStatus(address agent) external view returns (AgentStatus memory) {\n        return _agentStatus(agent);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status) {\n        return _getAgent(index);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory) {\n        return _disputes[agentIndex];\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns status of the given agent: (flag, domain, index).\n    function _agentStatus(address agent) internal view returns (AgentStatus memory) {\n        return IAgentManager(agentManager).agentStatus(agent);\n    }\n\n    /// @dev Returns agent and their status for a given agent index. Returns zero values for non existing indexes.\n    function _getAgent(uint256 index) internal view returns (address agent, AgentStatus memory status) {\n        return IAgentManager(agentManager).getAgent(index);\n    }\n\n    /// @dev Checks if a Dispute exists for the given Notary. This function returns true, if\n    /// Notary is in ongoing Dispute, or if Dispute was resolved not in Notary's favor.\n    /// In both cases we can't trust Notary's data.\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeExists(uint32 notaryIndex) internal view returns (bool) {\n        return _disputes[notaryIndex].flag != DisputeFlag.None;\n    }\n\n    /// @dev Checks if a Notary recently won a Dispute and is still in the \"post-dispute\" timeout period.\n    /// In this period we still can't trust Notary's data, though we can optimistically assume that\n    /// that the data will be correct after the timeout (assuming no new Disputes are opened).\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeTimeout(uint32 notaryIndex) internal view returns (bool) {\n        DisputeStatus memory status = _disputes[notaryIndex];\n        // Exit early if Notary is in ongoing Dispute / slashed.\n        if (status.flag != DisputeFlag.None) return false;\n        // Check if Notary has been in any Dispute at all.\n        if (status.openedAt == 0) return false;\n        // Otherwise check if the Dispute timeout is still active.\n        return block.timestamp \u003c status.resolvedAt + DISPUTE_TIMEOUT_NOTARY;\n    }\n}\n\n// contracts/hubs/StateHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StateHub` is a parent contract for `Origin`. It is responsible for the following:\n/// - Keeping track of the historical Origin Merkle Tree containing all the message hashes.\n/// - Keeping track of the historical Origin States, as well as verifying their validity.\nabstract contract StateHub is AgentSecured, StateHubEvents, IStateHub {\n    using SafeCast for uint256;\n    using StateLib for bytes;\n\n    struct OriginState {\n        uint40 blockNumber;\n        uint40 timestamp;\n        GasData gasData;\n    }\n    // Bits left for tight packing: 80\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Historical Merkle Tree\n    /// Note: Takes two storage slots\n    HistoricalTree private _tree;\n\n    /// @dev All historical contract States\n    OriginState[] private _originStates;\n\n    /// @dev gap for upgrade safety\n    uint256[47] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IStateHub\n    function isValidState(bytes memory statePayload) external view returns (bool isValid) {\n        // This will revert if payload is not a formatted state\n        State state = statePayload.castToState();\n        return _isValidState(state);\n    }\n\n    /// @inheritdoc IStateHub\n    function statesAmount() external view returns (uint256) {\n        return _originStates.length;\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestLatestState() external view returns (bytes memory stateData) {\n        // This never underflows, assuming the contract was initialized\n        return suggestState(_nextNonce() - 1);\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestState(uint32 nonce) public view returns (bytes memory stateData) {\n        // This will revert if nonce is out of range\n        bytes32 root = _tree.root(nonce);\n        return _formatOriginState(_originStates[nonce], root, localDomain, nonce);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Initializes the saved states list by inserting a state for an empty Merkle Tree.\n    function _initializeStates() internal {\n        // This should only be called once, when the contract is initialized\n        // This will revert if _tree.roots is non-empty\n        bytes32 savedRoot = _tree.initializeRoots();\n        // Save root for empty merkle _tree with block number and timestamp of initialization\n        _saveState(savedRoot, _toOriginState());\n    }\n\n    /// @dev Inserts leaf into the Merkle Tree and saves the updated origin State.\n    function _insertAndSave(bytes32 leaf) internal {\n        bytes32 newRoot = _tree.insert(leaf);\n        _saveState(newRoot, _toOriginState());\n    }\n\n    /// @dev Saves an updated state of the Origin contract\n    function _saveState(bytes32 root, OriginState memory state) internal {\n        uint32 nonce = _nextNonce();\n        _originStates.push(state);\n        // Emit event with raw state data\n        emit StateSaved(_formatOriginState(state, root, localDomain, nonce));\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns nonce of the next sent message: the amount of saved States so far.\n    /// This always equals to \"total amount of sent messages\" plus 1.\n    function _nextNonce() internal view returns (uint32) {\n        // TODO: consider using more than 32 bits for origin nonces\n        return _originStates.length.toUint32();\n    }\n\n    /// @dev Checks if a state is valid, i.e. if it matches the historical one.\n    /// Reverts, if state refers to another Origin contract.\n    function _isValidState(State state) internal view returns (bool) {\n        // Check if state refers to this contract\n        if (state.origin() != localDomain) revert IncorrectOriginDomain();\n        // Check if nonce exists\n        uint32 nonce = state.nonce();\n        if (nonce \u003e= _originStates.length) return false;\n        // Check if state root matches the historical one\n        if (state.root() != _tree.root(nonce)) return false;\n        // Check if state metadata matches the historical one\n        return _areEqual(state, _originStates[nonce]);\n    }\n\n    // ═════════════════════════════════════════════ STRUCT FORMATTING ═════════════════════════════════════════════════\n\n    /// @dev Returns a formatted payload for a stored OriginState.\n    function _formatOriginState(OriginState memory originState, bytes32 root, uint32 origin, uint32 nonce)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return StateLib.formatState({\n            root_: root,\n            origin_: origin,\n            nonce_: nonce,\n            blockNumber_: originState.blockNumber,\n            timestamp_: originState.timestamp,\n            gasData_: originState.gasData\n        });\n    }\n\n    /// @dev Child contract should implement the logic for getting the current gas data from the gas oracle\n    /// to be saved as part of the Origin State.\n    // solhint-disable-next-line ordering\n    function _fetchGasData() internal view virtual returns (GasData);\n\n    /// @dev Returns a OriginState struct to save in the contract.\n    function _toOriginState() internal view returns (OriginState memory originState) {\n        originState.blockNumber = ChainContext.blockNumber();\n        originState.timestamp = ChainContext.blockTimestamp();\n        originState.gasData = _fetchGasData();\n    }\n\n    /// @dev Checks that a state and its Origin representation are equal.\n    function _areEqual(State state, OriginState memory originState) internal pure returns (bool) {\n        return state.blockNumber() == originState.blockNumber \u0026\u0026 state.timestamp() == originState.timestamp;\n    }\n}\n\n// contracts/Origin.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Origin` contract is used for sending messages to remote chains. It is done\n/// by inserting the message hashes into the Origin Merkle, which makes it possible to\n/// prove that message was sent using the Merkle proof against the Origin Merkle Root. This essentially\n/// compresses the list of messages into a single 32-byte value that needs to be stored on the destination chain.\n/// `Origin` is responsible for the following:\n/// - Formatting the sent message payloads, and inserting their hashes into the Origin Merkle Tree.\n/// - Keeping track of its own historical states (see parent contract `StateHub`).\n/// - Enforcing minimum tip values for sent base messages based on the provided execution requests.\n/// - Distributing the collected tips upon request from a local `AgentManager` contract.\ncontract Origin is StateHub, OriginEvents, InterfaceOrigin {\n    using MemViewLib for bytes;\n    using MessageLib for bytes;\n    using TipsLib for bytes;\n    using TypeCasts for address;\n\n    address public immutable gasOracle;\n\n    modifier onlyRemoteDestination(uint32 destination) {\n        if (destination == localDomain) revert IncorrectDestinationDomain();\n        _;\n    }\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_, address gasOracle_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {\n        gasOracle = gasOracle_;\n    }\n\n    /// @notice Initializes Origin contract:\n    /// - msg.sender is set as contract owner\n    /// - State of \"empty merkle tree\" is saved\n    function initialize() external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize \"states\": state of an \"empty merkle tree\" is saved\n        _initializeStates();\n    }\n\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable onlyRemoteDestination(destination) returns (uint32 messageNonce, bytes32 messageHash) {\n        // Check that content is not too large\n        if (content.length \u003e MAX_CONTENT_BYTES) revert ContentLengthTooBig();\n        // This will revert if msg.value is lower than value of minimum tips\n        Tips tips = _getMinimumTips(destination, paddedRequest, content.length).matchValue(msg.value);\n        Request request = RequestLib.wrapPadded(paddedRequest);\n        // Format the BaseMessage body\n        bytes memory body = BaseMessageLib.formatBaseMessage({\n            sender_: msg.sender.addressToBytes32(),\n            recipient_: recipient,\n            tips_: tips,\n            request_: request,\n            content_: content\n        });\n        // Send the message\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Base, body);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        onlyAgentManager\n        onlyRemoteDestination(destination)\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // AgentManager (checked via modifier) is responsible for constructing the calldata payload correctly.\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Manager, payload);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function withdrawTips(address recipient, uint256 amount) external onlyAgentManager {\n        if (address(this).balance \u003c amount) revert InsufficientEthBalance();\n        (bool success,) = recipient.call{value: amount}(\"\");\n        if (!success) revert EthTransferFailed();\n        emit TipWithdrawalCompleted(recipient, amount);\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue)\n    {\n        return _getMinimumTips(destination, paddedRequest, contentLength).value();\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Sends the given message to the specified destination. Message hash is inserted\n    /// into the Origin Merkle Tree, which will enable message execution on destination chain.\n    function _sendMessage(uint32 destination, uint32 optimisticPeriod, MessageFlag flag, bytes memory body)\n        internal\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // Format the message header\n        messageNonce = _nextNonce();\n        Header header = flag.encodeHeader({\n            origin_: localDomain,\n            nonce_: messageNonce,\n            destination_: destination,\n            optimisticPeriod_: optimisticPeriod\n        });\n        // Format the full message payload\n        bytes memory msgPayload = MessageLib.formatMessage(header, body);\n        // Insert new leaf into the Origin Merkle Tree and save the updated state\n        messageHash = msgPayload.castToMessage().leaf();\n        _insertAndSave(messageHash);\n        // Emit event with message information\n        emit Sent(messageHash, messageNonce, destination, msgPayload);\n        // Update the gas oracle data. We do this after the provided tips are checked so that\n        // the provided message is sent in the event that the gas oracle data is updated to a higher value.\n        InterfaceGasOracle(gasOracle).updateGasData(destination);\n        // TODO: consider doing this before the message is sent, while adjusting GasOracle.getMinimumTips() to\n        // use the pending gas oracle data.\n    }\n\n    /// @dev Returns the minimum tips for sending a message to the given destination with the given request and content.\n    function _getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        internal\n        view\n        returns (Tips)\n    {\n        return\n            TipsLib.wrapPadded(InterfaceGasOracle(gasOracle).getMinimumTips(destination, paddedRequest, contentLength));\n    }\n\n    /// @dev Gets the current gas data from the gas oracle to be saved as part of the Origin State.\n    function _fetchGasData() internal view override returns (GasData) {\n        return GasDataLib.wrapGasData(InterfaceGasOracle(gasOracle).getGasData());\n    }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[],"name":"IncorrectVersionLength","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"localDomain","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bool","name":"allowFailure","type":"bool"},{"internalType":"bytes","name":"callData","type":"bytes"}],"internalType":"struct MultiCallable.Call[]","name":"calls","type":"tuple[]"}],"name":"multicall","outputs":[{"components":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"bytes","name":"returnData","type":"bytes"}],"internalType":"struct MultiCallable.Result[]","name":"callResults","type":"tuple[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"synapseDomain","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"versionString","type":"string"}],"stateMutability":"view","type":"function"}],"userDoc":{"kind":"user","methods":{"localDomain()":{"notice":"Domain of the local chain, set once upon contract creation"},"multicall((bool,bytes)[])":{"notice":"Aggregates a few calls to this contract into one multicall without modifying `msg.sender`."}},"notice":"Base contract for all messaging contracts. - Provides context on the local chain's domain. - Provides ownership functionality. - Will be providing pausing functionality when it is implemented.","version":1},"developerDoc":{"kind":"dev","methods":{"acceptOwnership()":{"details":"The new owner accepts the ownership transfer."},"owner()":{"details":"Returns the address of the current owner."},"pendingOwner()":{"details":"Returns the address of the pending owner."},"renounceOwnership()":{"details":"Should be impossible to renounce ownership; we override OpenZeppelin OwnableUpgradeable's implementation of renounceOwnership to make it a no-op"},"transferOwnership(address)":{"details":"Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. Can only be called by the current owner."}},"stateVariables":{"__GAP":{"details":"gap for upgrade safety"}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"IncorrectVersionLength\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferStarted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"localDomain\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"allowFailure\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"struct MultiCallable.Call[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"multicall\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"struct MultiCallable.Result[]\",\"name\":\"callResults\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"synapseDomain\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"versionString\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"acceptOwnership()\":{\"details\":\"The new owner accepts the ownership transfer.\"},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pendingOwner()\":{\"details\":\"Returns the address of the pending owner.\"},\"renounceOwnership()\":{\"details\":\"Should be impossible to renounce ownership; we override OpenZeppelin OwnableUpgradeable's implementation of renounceOwnership to make it a no-op\"},\"transferOwnership(address)\":{\"details\":\"Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. Can only be called by the current owner.\"}},\"stateVariables\":{\"__GAP\":{\"details\":\"gap for upgrade safety\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"localDomain()\":{\"notice\":\"Domain of the local chain, set once upon contract creation\"},\"multicall((bool,bytes)[])\":{\"notice\":\"Aggregates a few calls to this contract into one multicall without modifying `msg.sender`.\"}},\"notice\":\"Base contract for all messaging contracts. - Provides context on the local chain's domain. - Provides ownership functionality. - Will be providing pausing functionality when it is implemented.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Origin.sol\":\"MessagingBase\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Origin.sol\":{\"keccak256\":\"0x96775924f147f3d1f8df8cdf56731fe52a15af8d8e12e608efb8158c112b18cd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e642a27f5fab3c62b4c02e9754e9e42b1cf2e5381dbea9d3d106d23b7772ebe6\",\"dweb:/ipfs/QmUwn7ZyBvPkjnMuK8ZMSexBUdNQnVtxwyoAyT4DXLQjra\"]}},\"version\":1}"},"hashes":{"acceptOwnership()":"79ba5097","localDomain()":"8d3638f4","multicall((bool,bytes)[])":"60fc8466","owner()":"8da5cb5b","pendingOwner()":"e30c3978","renounceOwnership()":"715018a6","synapseDomain()":"717b8638","transferOwnership(address)":"f2fde38b","version()":"54fd4d50"}},"solidity/Origin.sol:MultiCallable":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/OriginEvents.sol\n\n/// @notice A collection of events emitted by the Origin contract\nabstract contract OriginEvents {\n    /**\n     * @notice Emitted when a new message is sent.\n     * @param messageHash   Hash of message; the leaf inserted to the Merkle tree for the message\n     * @param nonce         Nonce of sent message (starts from 1)\n     * @param destination   Destination domain\n     * @param message       Raw bytes of message\n     */\n    event Sent(bytes32 indexed messageHash, uint32 indexed nonce, uint32 indexed destination, bytes message);\n\n    /**\n     * @notice Emitted when a tip withdrawal is completed.\n     * @param actor     Actor address\n     * @param tip       Tip value, denominated in local domain's wei\n     */\n    event TipWithdrawalCompleted(address actor, uint256 tip);\n}\n\n// contracts/events/StateHubEvents.sol\n\n/// @notice A collection of events emitted by the StateHub contract\nabstract contract StateHubEvents {\n    /**\n     * @notice Emitted when a new Origin State is saved after a message was sent.\n     * @param state     Raw payload with state data\n     */\n    event StateSaved(bytes state);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n    /**\n     * @notice Check that a given state is valid: matches the historical state of Origin contract.\n     * Note: any Agent including an invalid state in their snapshot will be slashed\n     * upon providing the snapshot and agent signature for it to Origin contract.\n     * @dev Will revert if any of these is true:\n     *  - State payload is not properly formatted.\n     * @param statePayload      Raw payload with state data\n     * @return isValid          Whether the provided state is valid\n     */\n    function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns the amount of saved states so far.\n     * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n     */\n    function statesAmount() external view returns (uint256);\n\n    /**\n     * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @return statePayload     Raw payload with the latest state data\n     */\n    function suggestLatestState() external view returns (bytes memory statePayload);\n\n    /**\n     * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @param nonce             Historical nonce to form a state\n     * @return statePayload     Raw payload with historical state data\n     */\n    function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/InterfaceGasOracle.sol\n\ninterface InterfaceGasOracle {\n    /**\n     * @notice Fetches the latest gas data for the chain from `Destination` contract,\n     * and uses it to update the oracle values for the requested chain.\n     * @param domain    Domain to update the gas data for\n     */\n    function updateGasData(uint32 domain) external;\n\n    /**\n     * @notice Returns the gas data for the local chain.\n     */\n    function getGasData() external view returns (uint256 paddedGasData);\n\n    /**\n     * @notice Returns the gas data for the given domain, in the decoded format.\n     * @param domain        Domain of chain to get gas data for\n     * @return gasPrice     Gas price for the chain (in Wei per gas unit)\n     * @return dataPrice    Calldata price (in Wei per byte of content)\n     * @return execBuffer   Tx fee safety buffer for message execution (in Wei)\n     * @return amortAttCost Amortized cost for attestation submission (in Wei)\n     * @return etherPrice   Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n     * @return markup       Markup for the message execution (in BWAD)\n     */\n    function getDecodedGasData(uint32 domain)\n        external\n        view\n        returns (\n            uint256 gasPrice,\n            uint256 dataPrice,\n            uint256 execBuffer,\n            uint256 amortAttCost,\n            uint256 etherPrice,\n            uint256 markup\n        );\n\n    /**\n     * @notice Returns the minimum tips for sending a message to a given destination.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return paddedTips       Padded encoded minimum tips information\n     */\n    function getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 paddedTips);\n}\n\n// contracts/interfaces/InterfaceOrigin.sol\n\ninterface InterfaceOrigin {\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /**\n     * @notice Send a message to the recipient located on destination domain.\n     * @dev Recipient has to conform to IMessageRecipient interface, otherwise message won't be delivered.\n     * Will revert if any of these is true:\n     * - `destination` is equal to contract's local domain\n     * - `content` length is greater than `MAX_CONTENT_BYTES`\n     * - `msg.value` is lower than value of minimum tips for the given message\n     * @param destination           Domain of destination chain\n     * @param recipient             Address of recipient on destination chain as bytes32\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param paddedRequest         Padded encoded message execution request on destination chain\n     * @param content               Raw bytes content of message\n     * @return messageNonce         Nonce of the sent message\n     * @return messageHash          Hash of the sent message\n     */\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable returns (uint32 messageNonce, bytes32 messageHash);\n\n    /**\n     * @notice Send a manager message to the destination domain.\n     * @dev This could only be called by AgentManager, which takes care of encoding the calldata payload.\n     * Note: (msgOrigin, proofMaturity) security args will be added to payload on the destination chain\n     * so that the AgentManager could verify where the Manager Message came from and how mature is the proof.\n     * Note: function is not payable, as no tips are required for sending a manager message.\n     * Will revert if `destination` is equal to contract's local domain.\n     * @param destination           Domain of destination chain\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param payload               Payload for calling AgentManager on destination chain (with extra security args)\n     */\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        returns (uint32 messageNonce, bytes32 messageHash);\n\n    // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Withdraws locked base message tips to the recipient.\n     * @dev Could only be called by a local AgentManager.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function withdrawTips(address recipient, uint256 amount) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the minimum tips value for sending a message to a given destination.\n     * @dev Using at least `tipsValue` as `msg.value` for `sendBaseMessage()`\n     * will guarantee that the message will be accepted.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return tipsValue        Minimum tips value for a message to be accepted\n     */\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue);\n}\n\n// contracts/libs/Constants.sol\n\n// Here we define common constants to enable their easier reusing later.\n\n// ══════════════════════════════════ MERKLE ═══════════════════════════════════\n/// @dev Height of the Agent Merkle Tree\nuint256 constant AGENT_TREE_HEIGHT = 32;\n/// @dev Height of the Origin Merkle Tree\nuint256 constant ORIGIN_TREE_HEIGHT = 32;\n/// @dev Height of the Snapshot Merkle Tree. Allows up to 64 leafs, e.g. up to 32 states\nuint256 constant SNAPSHOT_TREE_HEIGHT = 6;\n// ══════════════════════════════════ STRUCTS ══════════════════════════════════\n/// @dev See Attestation.sol: (bytes32,bytes32,uint32,uint40,uint40): 32+32+4+5+5\nuint256 constant ATTESTATION_LENGTH = 78;\n/// @dev See GasData.sol: (uint16,uint16,uint16,uint16,uint16,uint16): 2+2+2+2+2+2\nuint256 constant GAS_DATA_LENGTH = 12;\n/// @dev See Receipt.sol: (uint32,uint32,bytes32,bytes32,uint8,address,address,address): 4+4+32+32+1+20+20+20\nuint256 constant RECEIPT_LENGTH = 133;\n/// @dev See State.sol: (bytes32,uint32,uint32,uint40,uint40,GasData): 32+4+4+5+5+len(GasData)\nuint256 constant STATE_LENGTH = 50 + GAS_DATA_LENGTH;\n/// @dev Maximum amount of states in a single snapshot. Each state produces two leafs in the tree\nuint256 constant SNAPSHOT_MAX_STATES = 1 \u003c\u003c (SNAPSHOT_TREE_HEIGHT - 1);\n// ══════════════════════════════════ MESSAGE ══════════════════════════════════\n/// @dev See Header.sol: (uint8,uint32,uint32,uint32,uint32): 1+4+4+4+4\nuint256 constant HEADER_LENGTH = 17;\n/// @dev See Request.sol: (uint96,uint64,uint32): 12+8+4\nuint256 constant REQUEST_LENGTH = 24;\n/// @dev See Tips.sol: (uint64,uint64,uint64,uint64): 8+8+8+8\nuint256 constant TIPS_LENGTH = 32;\n/// @dev The amount of discarded last bits when encoding tip values\nuint256 constant TIPS_GRANULARITY = 32;\n/// @dev Tip values could be only the multiples of TIPS_MULTIPLIER\nuint256 constant TIPS_MULTIPLIER = 1 \u003c\u003c TIPS_GRANULARITY;\n// ══════════════════════════════ STATEMENT SALTS ══════════════════════════════\n/// @dev Salts for signing various statements\nbytes32 constant ATTESTATION_VALID_SALT = keccak256(\"ATTESTATION_VALID_SALT\");\nbytes32 constant ATTESTATION_INVALID_SALT = keccak256(\"ATTESTATION_INVALID_SALT\");\nbytes32 constant RECEIPT_VALID_SALT = keccak256(\"RECEIPT_VALID_SALT\");\nbytes32 constant RECEIPT_INVALID_SALT = keccak256(\"RECEIPT_INVALID_SALT\");\nbytes32 constant SNAPSHOT_VALID_SALT = keccak256(\"SNAPSHOT_VALID_SALT\");\nbytes32 constant STATE_INVALID_SALT = keccak256(\"STATE_INVALID_SALT\");\n// ═════════════════════════════════ PROTOCOL ══════════════════════════════════\n/// @dev Optimistic period for new agent roots in LightManager\nuint32 constant AGENT_ROOT_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Timeout between the agent root could be proposed and resolved in LightManager\nuint32 constant AGENT_ROOT_PROPOSAL_TIMEOUT = 12 hours;\nuint32 constant BONDING_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Amount of time that the Notary will not be considered active after they won a dispute\nuint32 constant DISPUTE_TIMEOUT_NOTARY = 12 hours;\n/// @dev Amount of time without fresh data from Notaries before contract owner can resolve stuck disputes manually\nuint256 constant FRESH_DATA_TIMEOUT = 4 hours;\n/// @dev Maximum bytes per message = 2 KiB (somewhat arbitrarily set to begin)\nuint256 constant MAX_CONTENT_BYTES = 2 * 2 ** 10;\n/// @dev Maximum value for the summit tip that could be set in GasOracle\nuint256 constant MAX_SUMMIT_TIP = 0.01 ether;\n\n// contracts/libs/Errors.sol\n\n// ══════════════════════════════ INVALID CALLER ═══════════════════════════════\n\nerror CallerNotAgentManager();\nerror CallerNotDestination();\nerror CallerNotInbox();\nerror CallerNotSummit();\n\n// ══════════════════════════════ INCORRECT DATA ═══════════════════════════════\n\nerror IncorrectAttestation();\nerror IncorrectAgentDomain();\nerror IncorrectAgentIndex();\nerror IncorrectAgentProof();\nerror IncorrectAgentRoot();\nerror IncorrectDataHash();\nerror IncorrectDestinationDomain();\nerror IncorrectOriginDomain();\nerror IncorrectSnapshotProof();\nerror IncorrectSnapshotRoot();\nerror IncorrectState();\nerror IncorrectStatesAmount();\nerror IncorrectTipsProof();\nerror IncorrectVersionLength();\n\nerror IncorrectNonce();\nerror IncorrectSender();\nerror IncorrectRecipient();\n\nerror FlagOutOfRange();\nerror IndexOutOfRange();\nerror NonceOutOfRange();\n\nerror OutdatedNonce();\n\nerror UnformattedAttestation();\nerror UnformattedAttestationReport();\nerror UnformattedBaseMessage();\nerror UnformattedCallData();\nerror UnformattedCallDataPrefix();\nerror UnformattedMessage();\nerror UnformattedReceipt();\nerror UnformattedReceiptReport();\nerror UnformattedSignature();\nerror UnformattedSnapshot();\nerror UnformattedState();\nerror UnformattedStateReport();\n\n// ═══════════════════════════════ MERKLE TREES ════════════════════════════════\n\nerror LeafNotProven();\nerror MerkleTreeFull();\nerror NotEnoughLeafs();\nerror TreeHeightTooLow();\n\n// ═════════════════════════════ OPTIMISTIC PERIOD ═════════════════════════════\n\nerror BaseClientOptimisticPeriod();\nerror MessageOptimisticPeriod();\nerror SlashAgentOptimisticPeriod();\nerror WithdrawTipsOptimisticPeriod();\nerror ZeroProofMaturity();\n\n// ═══════════════════════════════ AGENT MANAGER ═══════════════════════════════\n\nerror AgentNotGuard();\nerror AgentNotNotary();\n\nerror AgentCantBeAdded();\nerror AgentNotActive();\nerror AgentNotActiveNorUnstaking();\nerror AgentNotFraudulent();\nerror AgentNotUnstaking();\nerror AgentUnknown();\n\nerror AgentRootNotProposed();\nerror AgentRootTimeoutNotOver();\n\nerror NotStuck();\n\nerror DisputeAlreadyResolved();\nerror DisputeNotOpened();\nerror DisputeTimeoutNotOver();\nerror GuardInDispute();\nerror NotaryInDispute();\n\nerror MustBeSynapseDomain();\nerror SynapseDomainForbidden();\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\nerror AlreadyExecuted();\nerror AlreadyFailed();\nerror DuplicatedSnapshotRoot();\nerror IncorrectMagicValue();\nerror GasLimitTooLow();\nerror GasSuppliedTooLow();\n\n// ══════════════════════════════════ ORIGIN ═══════════════════════════════════\n\nerror ContentLengthTooBig();\nerror EthTransferFailed();\nerror InsufficientEthBalance();\n\n// ════════════════════════════════ GAS ORACLE ═════════════════════════════════\n\nerror LocalGasDataNotSet();\nerror RemoteGasDataNotSet();\n\n// ═══════════════════════════════════ TIPS ════════════════════════════════════\n\nerror SummitTipTooHigh();\nerror TipsClaimMoreThanEarned();\nerror TipsClaimZero();\nerror TipsOverflow();\nerror TipsValueTooLow();\n\n// ════════════════════════════════ MEMORY VIEW ════════════════════════════════\n\nerror IndexedTooMuch();\nerror ViewOverrun();\nerror OccupiedMemory();\nerror UnallocatedMemory();\nerror PrecompileOutOfGas();\n\n// ═════════════════════════════════ MULTICALL ═════════════════════════════════\n\nerror MulticallFailed();\n\n// contracts/libs/TypeCasts.sol\n\nlibrary TypeCasts {\n    // alignment preserving cast\n    function addressToBytes32(address addr) internal pure returns (bytes32) {\n        return bytes32(uint256(uint160(addr)));\n    }\n\n    // alignment preserving cast\n    function bytes32ToAddress(bytes32 buf) internal pure returns (address) {\n        return address(uint160(uint256(buf)));\n    }\n}\n\n// contracts/libs/stack/Number.sol\n\n/// Number is a compact representation of uint256, that is fit into 16 bits\n/// with the maximum relative error under 0.4%.\ntype Number is uint16;\n\nusing NumberLib for Number global;\n\n/// # Number\n/// Library for compact representation of uint256 numbers.\n/// - Number is stored using mantissa and exponent, each occupying 8 bits.\n/// - Numbers under 2**8 are stored as `mantissa` with `exponent = 0xFF`.\n/// - Numbers at least 2**8 are approximated as `(256 + mantissa) \u003c\u003c exponent`\n/// \u003e - `0 \u003c= mantissa \u003c 256`\n/// \u003e - `0 \u003c= exponent \u003c= 247` (`256 * 2**248` doesn't fit into uint256)\n/// # Number stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type  | Bytes |\n/// | ---------- | -------- | ----- | ----- |\n/// | (002..001] | mantissa | uint8 | 1     |\n/// | (001..000] | exponent | uint8 | 1     |\n\nlibrary NumberLib {\n    /// @dev Amount of bits to shift to mantissa field\n    uint16 private constant SHIFT_MANTISSA = 8;\n\n    /// @notice For bwad math (binary wad) we use 2**64 as \"wad\" unit.\n    /// @dev We are using not using 10**18 as wad, because it is not stored precisely in NumberLib.\n    uint256 internal constant BWAD_SHIFT = 64;\n    uint256 internal constant BWAD = 1 \u003c\u003c BWAD_SHIFT;\n    /// @notice ~0.1% in bwad units.\n    uint256 internal constant PER_MILLE_SHIFT = BWAD_SHIFT - 10;\n    uint256 internal constant PER_MILLE = 1 \u003c\u003c PER_MILLE_SHIFT;\n\n    /// @notice Compresses uint256 number into 16 bits.\n    function compress(uint256 value) internal pure returns (Number) {\n        // Find `msb` such as `2**msb \u003c= value \u003c 2**(msb + 1)`\n        uint256 msb = mostSignificantBit(value);\n        // We want to preserve 9 bits of precision.\n        // The highest bit is always 1, so we can skip it.\n        // The remaining 8 highest bits are stored as mantissa.\n        if (msb \u003c 8) {\n            // Value is less than 2**8, so we can use value as mantissa with \"-1\" exponent.\n            return _encode(uint8(value), 0xFF);\n        } else {\n            // We use `msb - 8` as exponent otherwise. Note that `exponent \u003e= 0`.\n            unchecked {\n                uint256 exponent = msb - 8;\n                // Shifting right by `msb-8` bits will shift the \"remaining 8 highest bits\" into the 8 lowest bits.\n                // uint8() will truncate the highest bit.\n                return _encode(uint8(value \u003e\u003e exponent), uint8(exponent));\n            }\n        }\n    }\n\n    /// @notice Decompresses 16 bits number into uint256.\n    /// @dev The outcome is an approximation of the original number: `(value - value / 256) \u003c number \u003c= value`.\n    function decompress(Number number) internal pure returns (uint256 value) {\n        // Isolate 8 highest bits as the mantissa.\n        uint256 mantissa = Number.unwrap(number) \u003e\u003e SHIFT_MANTISSA;\n        // This will truncate the highest bits, leaving only the exponent.\n        uint256 exponent = uint8(Number.unwrap(number));\n        if (exponent == 0xFF) {\n            return mantissa;\n        } else {\n            unchecked {\n                return (256 + mantissa) \u003c\u003c (exponent);\n            }\n        }\n    }\n\n    /// @dev Returns the most significant bit of `x`\n    /// https://solidity-by-example.org/bitwise/\n    function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\n        // To find `msb` we determine it bit by bit, starting from the highest one.\n        // `0 \u003c= msb \u003c= 255`, so we start from the highest bit, 1\u003c\u003c7 == 128.\n        // If `x` is at least 2**128, then the highest bit of `x` is at least 128.\n        // solhint-disable no-inline-assembly\n        assembly {\n            // `f` is set to 1\u003c\u003c7 if `x \u003e= 2**128` and to 0 otherwise.\n            let f := shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\n            // If `x \u003e= 2**128` then set `msb` highest bit to 1 and shift `x` right by 128.\n            // Otherwise, `msb` remains 0 and `x` remains unchanged.\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        // `x` is now at most 2**128 - 1. Continue the same way, the next highest bit is 1\u003c\u003c6 == 64.\n        assembly {\n            // `f` is set to 1\u003c\u003c6 if `x \u003e= 2**64` and to 0 otherwise.\n            let f := shl(6, gt(x, 0xFFFFFFFFFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c5 if `x \u003e= 2**32` and to 0 otherwise.\n            let f := shl(5, gt(x, 0xFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c4 if `x \u003e= 2**16` and to 0 otherwise.\n            let f := shl(4, gt(x, 0xFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c3 if `x \u003e= 2**8` and to 0 otherwise.\n            let f := shl(3, gt(x, 0xFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c2 if `x \u003e= 2**4` and to 0 otherwise.\n            let f := shl(2, gt(x, 0xF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c1 if `x \u003e= 2**2` and to 0 otherwise.\n            let f := shl(1, gt(x, 0x3))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1 if `x \u003e= 2**1` and to 0 otherwise.\n            let f := gt(x, 0x1)\n            msb := or(msb, f)\n        }\n    }\n\n    /// @dev Wraps (mantissa, exponent) pair into Number.\n    function _encode(uint8 mantissa, uint8 exponent) private pure returns (Number) {\n        // Casts below are upcasts, so they are safe.\n        return Number.wrap(uint16(mantissa) \u003c\u003c SHIFT_MANTISSA | uint16(exponent));\n    }\n}\n\n// contracts/libs/stack/Request.sol\n\n/// Request is encoded data with \"message execution request\".\ntype Request is uint192;\n\nusing RequestLib for Request global;\n\n/// Library for formatting _the request part_ of _the base messages_.\n/// - Request represents a message sender requirements for the message execution on the destination chain.\n/// - Request occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n/// \u003e gasDrop field is included for future compatibility and is ignored at the moment.\n///\n/// # Request stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type   | Bytes | Description                                          |\n/// | ---------- | -------- | ------ | ----- | ---------------------------------------------------- |\n/// | (024..012] | gasDrop  | uint96 | 12    | Minimum amount of gas token to drop to the recipient |\n/// | (012..004] | gasLimit | uint64 | 8     | Minimum amount of gas units to supply for execution  |\n/// | (004..000] | version  | uint32 | 4     | Base message version to pass to the recipient        |\n\nlibrary RequestLib {\n    /// @dev Amount of bits to shift to gasDrop field\n    uint192 private constant SHIFT_GAS_DROP = 12 * 8;\n    /// @dev Amount of bits to shift to gasLimit field\n    uint192 private constant SHIFT_GAS_LIMIT = 4 * 8;\n\n    /// @notice Returns an encoded request with the given fields\n    /// @param gasDrop_     Minimum amount of gas token to drop to the recipient (ignored at the moment)\n    /// @param gasLimit_    Minimum amount of gas units to supply for execution\n    /// @param version_     Base message version to pass to the recipient\n    function encodeRequest(uint96 gasDrop_, uint64 gasLimit_, uint32 version_) internal pure returns (Request) {\n        // Casts below are upcasts, so they are safe\n        return Request.wrap(uint192(gasDrop_) \u003c\u003c SHIFT_GAS_DROP | uint192(gasLimit_) \u003c\u003c SHIFT_GAS_LIMIT | version_);\n    }\n\n    /// @notice Wraps the padded encoded request into a Request-typed value.\n    /// @dev The \"padded\" request is simply an encoded request casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded requests\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedRequest) internal pure returns (Request) {\n        // Casting to uint192 will truncate the highest bits, which is the behavior we want\n        return Request.wrap(uint192(paddedRequest));\n    }\n\n    /// @notice Returns the requested of gas token to drop to the recipient.\n    function gasDrop(Request request) internal pure returns (uint96) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return uint96(Request.unwrap(request) \u003e\u003e SHIFT_GAS_DROP);\n    }\n\n    /// @notice Returns the requested minimum amount of gas units to supply for execution.\n    function gasLimit(Request request) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Request.unwrap(request) \u003e\u003e SHIFT_GAS_LIMIT);\n    }\n\n    /// @notice Returns the requested base message version to pass to the recipient.\n    function version(Request request) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Request.unwrap(request));\n    }\n}\n\n// node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        require(value \u003c= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        require(value \u003c= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        require(value \u003c= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value \u003c= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        require(value \u003c= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        require(value \u003c= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        require(value \u003c= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        require(value \u003c= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        require(value \u003c= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        require(value \u003c= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        require(value \u003c= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        require(value \u003c= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        require(value \u003c= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        require(value \u003c= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        require(value \u003c= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value \u003c= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        require(value \u003c= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        require(value \u003c= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        require(value \u003c= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value \u003c= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        require(value \u003c= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        require(value \u003c= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        require(value \u003c= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value \u003c= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        require(value \u003c= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        require(value \u003c= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        require(value \u003c= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value \u003c= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        require(value \u003c= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value \u003c= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value \u003c= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     *\n     * _Available since v3.0._\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value \u003e= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     *\n     * _Available since v3.0._\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value \u003c= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     *\n     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length \u003e 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance \u003e= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance \u003e= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length \u003e 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n\n// contracts/base/MultiCallable.sol\n\n/// @notice Collection of Multicall utilities. Fork of Multicall3:\n/// https://github.com/mds1/multicall/blob/master/src/Multicall3.sol\nabstract contract MultiCallable {\n    struct Call {\n        bool allowFailure;\n        bytes callData;\n    }\n\n    struct Result {\n        bool success;\n        bytes returnData;\n    }\n\n    /// @notice Aggregates a few calls to this contract into one multicall without modifying `msg.sender`.\n    function multicall(Call[] calldata calls) external returns (Result[] memory callResults) {\n        uint256 amount = calls.length;\n        callResults = new Result[](amount);\n        Call calldata call_;\n        for (uint256 i = 0; i \u003c amount;) {\n            call_ = calls[i];\n            Result memory result = callResults[i];\n            // We perform a delegate call to ourselves here. Delegate call does not modify `msg.sender`, so\n            // this will have the same effect as if `msg.sender` performed all the calls themselves one by one.\n            // solhint-disable-next-line avoid-low-level-calls\n            (result.success, result.returnData) = address(this).delegatecall(call_.callData);\n            // solhint-disable-next-line no-inline-assembly\n            assembly {\n                // Revert if the call fails and failure is not allowed\n                // `allowFailure := calldataload(call_)` and `success := mload(result)`\n                if iszero(or(calldataload(call_), mload(result))) {\n                    // Revert with `0x4d6a2328` (function selector for `MulticallFailed()`)\n                    mstore(0x00, 0x4d6a232800000000000000000000000000000000000000000000000000000000)\n                    revert(0x00, 0x04)\n                }\n            }\n            unchecked {\n                ++i;\n            }\n        }\n    }\n}\n\n// contracts/base/Version.sol\n\n/**\n * @title Versioned\n * @notice Version getter for contracts. Doesn't use any storage slots, meaning\n * it will never cause any troubles with the upgradeable contracts. For instance, this contract\n * can be added or removed from the inheritance chain without shifting the storage layout.\n */\nabstract contract Versioned {\n    /**\n     * @notice Struct that is mimicking the storage layout of a string with 32 bytes or less.\n     * Length is limited by 32, so the whole string payload takes two memory words:\n     * @param length    String length\n     * @param data      String characters\n     */\n    struct _ShortString {\n        uint256 length;\n        bytes32 data;\n    }\n\n    /// @dev Length of the \"version string\"\n    uint256 private immutable _length;\n    /// @dev Bytes representation of the \"version string\".\n    /// Strings with length over 32 are not supported!\n    bytes32 private immutable _data;\n\n    constructor(string memory version_) {\n        _length = bytes(version_).length;\n        if (_length \u003e 32) revert IncorrectVersionLength();\n        // bytes32 is left-aligned =\u003e this will store the byte representation of the string\n        // with the trailing zeroes to complete the 32-byte word\n        _data = bytes32(bytes(version_));\n    }\n\n    function version() external view returns (string memory versionString) {\n        // Load the immutable values to form the version string\n        _ShortString memory str = _ShortString(_length, _data);\n        // The only way to do this cast is doing some dirty assembly\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            versionString := str\n        }\n    }\n}\n\n// contracts/libs/ChainContext.sol\n\n/// @notice Library for accessing chain context variables as tightly packed integers.\n/// Messaging contracts should rely on this library for accessing chain context variables\n/// instead of doing the casting themselves.\nlibrary ChainContext {\n    using SafeCast for uint256;\n\n    /// @notice Returns the current block number as uint40.\n    /// @dev Reverts if block number is greater than 40 bits, which is not supposed to happen\n    /// until the block.timestamp overflows (assuming block time is at least 1 second).\n    function blockNumber() internal view returns (uint40) {\n        return block.number.toUint40();\n    }\n\n    /// @notice Returns the current block timestamp as uint40.\n    /// @dev Reverts if block timestamp is greater than 40 bits, which is\n    /// supposed to happen approximately in year 36835.\n    function blockTimestamp() internal view returns (uint40) {\n        return block.timestamp.toUint40();\n    }\n\n    /// @notice Returns the chain id as uint32.\n    /// @dev Reverts if chain id is greater than 32 bits, which is not\n    /// supposed to happen in production.\n    function chainId() internal view returns (uint32) {\n        return block.chainid.toUint32();\n    }\n}\n\n// contracts/libs/Structures.sol\n\n// Here we define common enums and structures to enable their easier reusing later.\n\n// ═══════════════════════════════ AGENT STATUS ════════════════════════════════\n\n/// @dev Potential statuses for the off-chain bonded agent:\n/// - Unknown: never provided a bond =\u003e signature not valid\n/// - Active: has a bond in BondingManager =\u003e signature valid\n/// - Unstaking: has a bond in BondingManager, initiated the unstaking =\u003e signature not valid\n/// - Resting: used to have a bond in BondingManager, successfully unstaked =\u003e signature not valid\n/// - Fraudulent: proven to commit fraud, value in Merkle Tree not updated =\u003e signature not valid\n/// - Slashed: proven to commit fraud, value in Merkle Tree was updated =\u003e signature not valid\n/// Unstaked agent could later be added back to THE SAME domain by staking a bond again.\n/// Honest agent: Unknown -\u003e Active -\u003e unstaking -\u003e Resting -\u003e Active ...\n/// Malicious agent: Unknown -\u003e Active -\u003e Fraudulent -\u003e Slashed\n/// Malicious agent: Unknown -\u003e Active -\u003e Unstaking -\u003e Fraudulent -\u003e Slashed\nenum AgentFlag {\n    Unknown,\n    Active,\n    Unstaking,\n    Resting,\n    Fraudulent,\n    Slashed\n}\n\n/// @notice Struct for storing an agent in the BondingManager contract.\nstruct AgentStatus {\n    AgentFlag flag;\n    uint32 domain;\n    uint32 index;\n}\n// 184 bits available for tight packing\n\nusing StructureUtils for AgentStatus global;\n\n/// @notice Potential statuses of an agent in terms of being in dispute\n/// - None: agent is not in dispute\n/// - Pending: agent is in unresolved dispute\n/// - Slashed: agent was in dispute that lead to agent being slashed\n/// Note: agent who won the dispute has their status reset to None\nenum DisputeFlag {\n    None,\n    Pending,\n    Slashed\n}\n\n/// @notice Struct for storing dispute status of an agent.\n/// @param flag         Dispute flag: None/Pending/Slashed.\n/// @param openedAt     Timestamp when the latest agent dispute was opened (zero if not opened).\n/// @param resolvedAt   Timestamp when the latest agent dispute was resolved (zero if not resolved).\nstruct DisputeStatus {\n    DisputeFlag flag;\n    uint40 openedAt;\n    uint40 resolvedAt;\n}\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\n/// @notice Struct representing the status of Destination contract.\n/// @param snapRootTime     Timestamp when latest snapshot root was accepted\n/// @param agentRootTime    Timestamp when latest agent root was accepted\n/// @param notaryIndex      Index of Notary who signed the latest agent root\nstruct DestinationStatus {\n    uint40 snapRootTime;\n    uint40 agentRootTime;\n    uint32 notaryIndex;\n}\n\n// ═══════════════════════════════ EXECUTION HUB ═══════════════════════════════\n\n/// @notice Potential statuses of the message in Execution Hub.\n/// - None: there hasn't been a valid attempt to execute the message yet\n/// - Failed: there was a valid attempt to execute the message, but recipient reverted\n/// - Success: there was a valid attempt to execute the message, and recipient did not revert\n/// Note: message can be executed until its status is Success\nenum MessageStatus {\n    None,\n    Failed,\n    Success\n}\n\nlibrary StructureUtils {\n    /// @notice Checks that Agent is Active\n    function verifyActive(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active) {\n            revert AgentNotActive();\n        }\n    }\n\n    /// @notice Checks that Agent is Unstaking\n    function verifyUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Unstaking) {\n            revert AgentNotUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Active or Unstaking\n    function verifyActiveUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active \u0026\u0026 status.flag != AgentFlag.Unstaking) {\n            revert AgentNotActiveNorUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Fraudulent\n    function verifyFraudulent(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Fraudulent) {\n            revert AgentNotFraudulent();\n        }\n    }\n\n    /// @notice Checks that Agent is not Unknown\n    function verifyKnown(AgentStatus memory status) internal pure {\n        if (status.flag == AgentFlag.Unknown) {\n            revert AgentUnknown();\n        }\n    }\n}\n\n// contracts/libs/memory/MemView.sol\n\n/// @dev MemView is an untyped view over a portion of memory to be used instead of `bytes memory`\ntype MemView is uint256;\n\n/// @dev Attach library functions to MemView\nusing MemViewLib for MemView global;\n\n/// @notice Library for operations with the memory views.\n/// Forked from https://github.com/summa-tx/memview-sol with several breaking changes:\n/// - The codebase is ported to Solidity 0.8\n/// - Custom errors are added\n/// - The runtime type checking is replaced with compile-time check provided by User-Defined Value Types\n///   https://docs.soliditylang.org/en/latest/types.html#user-defined-value-types\n/// - uint256 is used as the underlying type for the \"memory view\" instead of bytes29.\n///   It is wrapped into MemView custom type in order not to be confused with actual integers.\n/// - Therefore the \"type\" field is discarded, allowing to allocate 16 bytes for both view location and length\n/// - The documentation is expanded\n/// - Library functions unused by the rest of the codebase are removed\n//  - Very pretty code separators are added :)\nlibrary MemViewLib {\n    /// @notice Stack layout for uint256 (from highest bits to lowest)\n    /// (32 .. 16]      loc     16 bytes    Memory address of underlying bytes\n    /// (16 .. 00]      len     16 bytes    Length of underlying bytes\n\n    // ═══════════════════════════════════════════ BUILDING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Instantiate a new untyped memory view. This should generally not be called directly.\n     * Prefer `ref` wherever possible.\n     * @param loc_          The memory address\n     * @param len_          The length\n     * @return The new view with the specified location and length\n     */\n    function build(uint256 loc_, uint256 len_) internal pure returns (MemView) {\n        uint256 end_ = loc_ + len_;\n        // Make sure that a view is not constructed that points to unallocated memory\n        // as this could be indicative of a buffer overflow attack\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            if gt(end_, mload(0x40)) { end_ := 0 }\n        }\n        if (end_ == 0) {\n            revert UnallocatedMemory();\n        }\n        return _unsafeBuildUnchecked(loc_, len_);\n    }\n\n    /**\n     * @notice Instantiate a memory view from a byte array.\n     * @dev Note that due to Solidity memory representation, it is not possible to\n     * implement a deref, as the `bytes` type stores its len in memory.\n     * @param arr           The byte array\n     * @return The memory view over the provided byte array\n     */\n    function ref(bytes memory arr) internal pure returns (MemView) {\n        uint256 len_ = arr.length;\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 loc_;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // We add 0x20, so that the view starts exactly where the array data starts\n            loc_ := add(arr, 0x20)\n        }\n        return build(loc_, len_);\n    }\n\n    // ════════════════════════════════════════════ CLONING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to the new memory.\n     * @param memView       The memory view\n     * @return arr          The cloned byte array\n     */\n    function clone(MemView memView) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        unchecked {\n            _unsafeCopyTo(memView, ptr + 0x20);\n        }\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 len_ = memView.len();\n        uint256 footprint_ = memView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    /**\n     * @notice Copies all views, joins them into a new bytearray.\n     * @param memViews      The memory views\n     * @return arr          The new byte array with joined data behind the given views\n     */\n    function join(MemView[] memory memViews) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        MemView newView;\n        unchecked {\n            newView = _unsafeJoin(memViews, ptr + 0x20);\n        }\n        uint256 len_ = newView.len();\n        uint256 footprint_ = newView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    // ══════════════════════════════════════════ INSPECTING MEMORY VIEW ═══════════════════════════════════════════════\n\n    /**\n     * @notice Returns the memory address of the underlying bytes.\n     * @param memView       The memory view\n     * @return loc_         The memory address\n     */\n    function loc(MemView memView) internal pure returns (uint256 loc_) {\n        // loc is stored in the highest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u003e\u003e 128;\n    }\n\n    /**\n     * @notice Returns the number of bytes of the view.\n     * @param memView       The memory view\n     * @return len_         The length of the view\n     */\n    function len(MemView memView) internal pure returns (uint256 len_) {\n        // len is stored in the lowest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u0026 type(uint128).max;\n    }\n\n    /**\n     * @notice Returns the endpoint of `memView`.\n     * @param memView       The memory view\n     * @return end_         The endpoint of `memView`\n     */\n    function end(MemView memView) internal pure returns (uint256 end_) {\n        // The endpoint never overflows uint128, let alone uint256, so we could use unchecked math here\n        unchecked {\n            return memView.loc() + memView.len();\n        }\n    }\n\n    /**\n     * @notice Returns the number of memory words this memory view occupies, rounded up.\n     * @param memView       The memory view\n     * @return words_       The number of memory words\n     */\n    function words(MemView memView) internal pure returns (uint256 words_) {\n        // returning ceil(length / 32.0)\n        unchecked {\n            return (memView.len() + 31) \u003e\u003e 5;\n        }\n    }\n\n    /**\n     * @notice Returns the in-memory footprint of a fresh copy of the view.\n     * @param memView       The memory view\n     * @return footprint_   The in-memory footprint of a fresh copy of the view.\n     */\n    function footprint(MemView memView) internal pure returns (uint256 footprint_) {\n        // words() * 32\n        return memView.words() \u003c\u003c 5;\n    }\n\n    // ════════════════════════════════════════════ HASHING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the keccak256 hash of the underlying memory\n     * @param memView       The memory view\n     * @return digest       The keccak256 hash of the underlying memory\n     */\n    function keccak(MemView memView) internal pure returns (bytes32 digest) {\n        uint256 loc_ = memView.loc();\n        uint256 len_ = memView.len();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            digest := keccak256(loc_, len_)\n        }\n    }\n\n    /**\n     * @notice Adds a salt to the keccak256 hash of the underlying data and returns the keccak256 hash of the\n     * resulting data.\n     * @param memView       The memory view\n     * @return digestSalted keccak256(salt, keccak256(memView))\n     */\n    function keccakSalted(MemView memView, bytes32 salt) internal pure returns (bytes32 digestSalted) {\n        return keccak256(bytes.concat(salt, memView.keccak()));\n    }\n\n    // ════════════════════════════════════════════ SLICING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Safe slicing without memory modification.\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the given index\n     */\n    function slice(MemView memView, uint256 index_, uint256 len_) internal pure returns (MemView) {\n        uint256 loc_ = memView.loc();\n        // Ensure it doesn't overrun the view\n        if (loc_ + index_ + len_ \u003e memView.end()) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // loc_ + index_ \u003c= memView.end()\n            return build({loc_: loc_ + index_, len_: len_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing bytes from `index` to end(memView).\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @return The new view for the slice starting from the given index until the initial view endpoint\n     */\n    function sliceFrom(MemView memView, uint256 index_) internal pure returns (MemView) {\n        uint256 len_ = memView.len();\n        // Ensure it doesn't overrun the view\n        if (index_ \u003e len_) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // index_ \u003c= len_ =\u003e memView.loc() + index_ \u003c= memView.loc() + memView.len() == memView.end()\n            return build({loc_: memView.loc() + index_, len_: len_ - index_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the first `len` bytes.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the initial view beginning\n     */\n    function prefix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        return memView.slice({index_: 0, len_: len_});\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the last `len` byte.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length until the initial view endpoint\n     */\n    function postfix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        uint256 viewLen = memView.len();\n        // Ensure it doesn't overrun the view\n        if (len_ \u003e viewLen) {\n            revert ViewOverrun();\n        }\n        // Could do the unchecked math due to the check above\n        uint256 index_;\n        unchecked {\n            index_ = viewLen - len_;\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // len_ \u003c= memView.len() =\u003e memView.loc() \u003c= loc_ \u003c= memView.end()\n            return build({loc_: memView.loc() + viewLen - len_, len_: len_});\n        }\n    }\n\n    // ═══════════════════════════════════════════ INDEXING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Load up to 32 bytes from the view onto the stack.\n     * @dev Returns a bytes32 with only the `bytes_` HIGHEST bytes set.\n     * This can be immediately cast to a smaller fixed-length byte array.\n     * To automatically cast to an integer, use `indexUint`.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return result       The 32 byte result having only `bytes_` highest bytes set\n     */\n    function index(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (bytes32 result) {\n        if (bytes_ == 0) {\n            return bytes32(0);\n        }\n        // Can't load more than 32 bytes to the stack in one go\n        if (bytes_ \u003e 32) {\n            revert IndexedTooMuch();\n        }\n        // The last indexed byte should be within view boundaries\n        if (index_ + bytes_ \u003e memView.len()) {\n            revert ViewOverrun();\n        }\n        uint256 bitLength = bytes_ \u003c\u003c 3; // bytes_ * 8\n        uint256 loc_ = memView.loc();\n        // Get a mask with `bitLength` highest bits set\n        uint256 mask;\n        // 0x800...00 binary representation is 100...00\n        // sar stands for \"signed arithmetic shift\": https://en.wikipedia.org/wiki/Arithmetic_shift\n        // sar(N-1, 100...00) = 11...100..00, with exactly N highest bits set to 1\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            mask := sar(sub(bitLength, 1), 0x8000000000000000000000000000000000000000000000000000000000000000)\n        }\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load a full word using index offset, and apply mask to ignore non-relevant bytes\n            result := and(mload(add(loc_, index_)), mask)\n        }\n    }\n\n    /**\n     * @notice Parse an unsigned integer from the view at `index`.\n     * @dev Requires that the view have \u003e= `bytes_` bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return The unsigned integer\n     */\n    function indexUint(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (uint256) {\n        bytes32 indexedBytes = memView.index(index_, bytes_);\n        // `index()` returns left-aligned `bytes_`, while integers are right-aligned\n        // Shifting here to right-align with the full 32 bytes word: need to shift right `(32 - bytes_)` bytes\n        unchecked {\n            // memView.index() reverts when bytes_ \u003e 32, thus unchecked math\n            return uint256(indexedBytes) \u003e\u003e ((32 - bytes_) \u003c\u003c 3);\n        }\n    }\n\n    /**\n     * @notice Parse an address from the view at `index`.\n     * @dev Requires that the view have \u003e= 20 bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @return The address\n     */\n    function indexAddress(MemView memView, uint256 index_) internal pure returns (address) {\n        // index 20 bytes as `uint160`, and then cast to `address`\n        return address(uint160(memView.indexUint(index_, 20)));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns a memory view over the specified memory location\n    /// without checking if it points to unallocated memory.\n    function _unsafeBuildUnchecked(uint256 loc_, uint256 len_) private pure returns (MemView) {\n        // There is no scenario where loc or len would overflow uint128, so we omit this check.\n        // We use the highest 128 bits to encode the location and the lowest 128 bits to encode the length.\n        return MemView.wrap((loc_ \u003c\u003c 128) | len_);\n    }\n\n    /**\n     * @notice Copy the view to a location, return an unsafe memory reference\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memView       The memory view\n     * @param newLoc        The new location to copy the underlying view data\n     * @return The memory view over the unsafe memory with the copied underlying data\n     */\n    function _unsafeCopyTo(MemView memView, uint256 newLoc) private view returns (MemView) {\n        uint256 len_ = memView.len();\n        uint256 oldLoc = memView.loc();\n\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (newLoc \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        bool res;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // use the identity precompile (0x04) to copy\n            res := staticcall(gas(), 0x04, oldLoc, len_, newLoc, len_)\n        }\n        if (!res) revert PrecompileOutOfGas();\n        return _unsafeBuildUnchecked({loc_: newLoc, len_: len_});\n    }\n\n    /**\n     * @notice Join the views in memory, return an unsafe reference to the memory.\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memViews      The memory views\n     * @return The conjoined view pointing to the new memory\n     */\n    function _unsafeJoin(MemView[] memory memViews, uint256 location) private view returns (MemView) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (location \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        // Copy the views to the specified location one by one, by tracking the amount of copied bytes so far\n        uint256 offset = 0;\n        for (uint256 i = 0; i \u003c memViews.length;) {\n            MemView memView = memViews[i];\n            // We can use the unchecked math here as location + sum(view.length) will never overflow uint256\n            unchecked {\n                _unsafeCopyTo(memView, location + offset);\n                offset += memView.len();\n                ++i;\n            }\n        }\n        return _unsafeBuildUnchecked({loc_: location, len_: offset});\n    }\n}\n\n// contracts/libs/merkle/MerkleMath.sol\n\nlibrary MerkleMath {\n    // ═════════════════════════════════════════ BASIC MERKLE CALCULATIONS ═════════════════════════════════════════════\n\n    /**\n     * @notice Calculates the merkle root for the given leaf and merkle proof.\n     * @dev Will revert if proof length exceeds the tree height.\n     * @param index     Index of `leaf` in tree\n     * @param leaf      Leaf of the merkle tree\n     * @param proof     Proof of inclusion of `leaf` in the tree\n     * @param height    Height of the merkle tree\n     * @return root_    Calculated Merkle Root\n     */\n    function proofRoot(uint256 index, bytes32 leaf, bytes32[] memory proof, uint256 height)\n        internal\n        pure\n        returns (bytes32 root_)\n    {\n        // Proof length could not exceed the tree height\n        uint256 proofLen = proof.length;\n        if (proofLen \u003e height) revert TreeHeightTooLow();\n        root_ = leaf;\n        /// @dev Apply unchecked to all ++h operations\n        unchecked {\n            // Go up the tree levels from the leaf following the proof\n            for (uint256 h = 0; h \u003c proofLen; ++h) {\n                // Get a sibling node on current level: this is proof[h]\n                root_ = getParent(root_, proof[h], index, h);\n            }\n            // Go up to the root: the remaining siblings are EMPTY\n            for (uint256 h = proofLen; h \u003c height; ++h) {\n                root_ = getParent(root_, bytes32(0), index, h);\n            }\n        }\n    }\n\n    /**\n     * @notice Calculates the parent of a node on the path from one of the leafs to root.\n     * @param node          Node on a path from tree leaf to root\n     * @param sibling       Sibling for a given node\n     * @param leafIndex     Index of the tree leaf\n     * @param nodeHeight    \"Level height\" for `node` (ZERO for leafs, ORIGIN_TREE_HEIGHT for root)\n     */\n    function getParent(bytes32 node, bytes32 sibling, uint256 leafIndex, uint256 nodeHeight)\n        internal\n        pure\n        returns (bytes32 parent)\n    {\n        // Index for `node` on its \"tree level\" is (leafIndex / 2**height)\n        // \"Left child\" has even index, \"right child\" has odd index\n        if ((leafIndex \u003e\u003e nodeHeight) \u0026 1 == 0) {\n            // Left child\n            return getParent(node, sibling);\n        } else {\n            // Right child\n            return getParent(sibling, node);\n        }\n    }\n\n    /// @notice Calculates the parent of tow nodes in the merkle tree.\n    /// @dev We use implementation with H(0,0) = 0\n    /// This makes EVERY empty node in the tree equal to ZERO,\n    /// saving us from storing H(0,0), H(H(0,0), H(0, 0)), and so on\n    /// @param leftChild    Left child of the calculated node\n    /// @param rightChild   Right child of the calculated node\n    /// @return parent      Value for the node having above mentioned children\n    function getParent(bytes32 leftChild, bytes32 rightChild) internal pure returns (bytes32 parent) {\n        if (leftChild == bytes32(0) \u0026\u0026 rightChild == bytes32(0)) {\n            return 0;\n        } else {\n            return keccak256(bytes.concat(leftChild, rightChild));\n        }\n    }\n\n    // ════════════════════════════════ ROOT/PROOF CALCULATION FOR A LIST OF LEAFS ═════════════════════════════════════\n\n    /**\n     * @notice Calculates merkle root for a list of given leafs.\n     * Merkle Tree is constructed by padding the list with ZERO values for leafs until list length is `2**height`.\n     * Merkle Root is calculated for the constructed tree, and then saved in `leafs[0]`.\n     * \u003e Note:\n     * \u003e - `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * \u003e - Caller is expected not to reuse `hashes` list after the call, and only use `leafs[0]` value,\n     * which is guaranteed to contain the calculated merkle root.\n     * \u003e - root is calculated using the `H(0,0) = 0` Merkle Tree implementation. See MerkleTree.sol for details.\n     * @dev Amount of leaves should be at most `2**height`\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param height    Height of the Merkle Tree to construct\n     */\n    function calculateRoot(bytes32[] memory hashes, uint256 height) internal pure {\n        uint256 levelLength = hashes.length;\n        // Amount of hashes could not exceed amount of leafs in tree with the given height\n        if (levelLength \u003e (1 \u003c\u003c height)) revert TreeHeightTooLow();\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\": the amount of iterations for the for loop above.\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n            }\n        }\n    }\n\n    /**\n     * @notice Generates a proof of inclusion of a leaf in the list. If the requested index is outside\n     * of the list range, generates a proof of inclusion for an empty leaf (proof of non-inclusion).\n     * The Merkle Tree is constructed by padding the list with ZERO values until list length is a power of two\n     * __AND__ index is in the extended list range. For example:\n     *  - `hashes.length == 6` and `0 \u003c= index \u003c= 7` will \"extend\" the list to 8 entries.\n     *  - `hashes.length == 6` and `7 \u003c index \u003c= 15` will \"extend\" the list to 16 entries.\n     * \u003e Note: `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * Caller is expected not to reuse `hashes` list after the call.\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param index     Leaf index to generate the proof for\n     * @return proof    Generated merkle proof\n     */\n    function calculateProof(bytes32[] memory hashes, uint256 index) internal pure returns (bytes32[] memory proof) {\n        // Use only meaningful values for the shortened proof\n        // Check if index is within the list range (we want to generates proofs for outside leafs as well)\n        uint256 height = getHeight(index \u003c hashes.length ? hashes.length : (index + 1));\n        proof = new bytes32[](height);\n        uint256 levelLength = hashes.length;\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Use sibling for the merkle proof; `index^1` is index of our sibling\n                proof[h] = (index ^ 1 \u003c levelLength) ? hashes[index ^ 1] : bytes32(0);\n\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\"\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n                // Traverse to parent node\n                index \u003e\u003e= 1;\n            }\n        }\n    }\n\n    /// @notice Returns the height of the tree having a given amount of leafs.\n    function getHeight(uint256 leafs) internal pure returns (uint256 height) {\n        uint256 amount = 1;\n        while (amount \u003c leafs) {\n            unchecked {\n                ++height;\n            }\n            amount \u003c\u003c= 1;\n        }\n    }\n}\n\n// contracts/libs/stack/GasData.sol\n\n/// GasData in encoded data with \"basic information about gas prices\" for some chain.\ntype GasData is uint96;\n\nusing GasDataLib for GasData global;\n\n/// ChainGas is encoded data with given chain's \"basic information about gas prices\".\ntype ChainGas is uint128;\n\nusing GasDataLib for ChainGas global;\n\n/// Library for encoding and decoding GasData and ChainGas structs.\n/// # GasData\n/// `GasData` is a struct to store the \"basic information about gas prices\", that could\n/// be later used to approximate the cost of a message execution, and thus derive the\n/// minimal tip values for sending a message to the chain.\n/// \u003e - `GasData` is supposed to be cached by `GasOracle` contract, allowing to store the\n/// \u003e approximates instead of the exact values, and thus save on storage costs.\n/// \u003e - For instance, if `GasOracle` only updates the values on +- 10% change, having an\n/// \u003e 0.4% error on the approximates would be acceptable.\n/// `GasData` is supposed to be included in the Origin's state, which are synced across\n/// chains using Agent-signed snapshots and attestations.\n/// ## GasData stack layout (from highest bits to lowest)\n///\n/// | Position   | Field        | Type   | Bytes | Description                                         |\n/// | ---------- | ------------ | ------ | ----- | --------------------------------------------------- |\n/// | (012..010] | gasPrice     | uint16 | 2     | Gas price for the chain (in Wei per gas unit)       |\n/// | (010..008] | dataPrice    | uint16 | 2     | Calldata price (in Wei per byte of content)         |\n/// | (008..006] | execBuffer   | uint16 | 2     | Tx fee safety buffer for message execution (in Wei) |\n/// | (006..004] | amortAttCost | uint16 | 2     | Amortized cost for attestation submission (in Wei)  |\n/// | (004..002] | etherPrice   | uint16 | 2     | Chain's Ether Price / Mainnet Ether Price (in BWAD) |\n/// | (002..000] | markup       | uint16 | 2     | Markup for the message execution (in BWAD)          |\n/// \u003e See Number.sol for more details on `Number` type and BWAD (binary WAD) math.\n///\n/// ## ChainGas stack layout (from highest bits to lowest)\n///\n/// | Position   | Field   | Type   | Bytes | Description      |\n/// | ---------- | ------- | ------ | ----- | ---------------- |\n/// | (016..004] | gasData | uint96 | 12    | Chain's gas data |\n/// | (004..000] | domain  | uint32 | 4     | Chain's domain   |\nlibrary GasDataLib {\n    /// @dev Amount of bits to shift to gasPrice field\n    uint96 private constant SHIFT_GAS_PRICE = 10 * 8;\n    /// @dev Amount of bits to shift to dataPrice field\n    uint96 private constant SHIFT_DATA_PRICE = 8 * 8;\n    /// @dev Amount of bits to shift to execBuffer field\n    uint96 private constant SHIFT_EXEC_BUFFER = 6 * 8;\n    /// @dev Amount of bits to shift to amortAttCost field\n    uint96 private constant SHIFT_AMORT_ATT_COST = 4 * 8;\n    /// @dev Amount of bits to shift to etherPrice field\n    uint96 private constant SHIFT_ETHER_PRICE = 2 * 8;\n\n    /// @dev Amount of bits to shift to gasData field\n    uint128 private constant SHIFT_GAS_DATA = 4 * 8;\n\n    // ═════════════════════════════════════════════════ GAS DATA ══════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded GasData struct with the given fields.\n    /// @param gasPrice_        Gas price for the chain (in Wei per gas unit)\n    /// @param dataPrice_       Calldata price (in Wei per byte of content)\n    /// @param execBuffer_      Tx fee safety buffer for message execution (in Wei)\n    /// @param amortAttCost_    Amortized cost for attestation submission (in Wei)\n    /// @param etherPrice_      Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n    /// @param markup_          Markup for the message execution (in BWAD)\n    function encodeGasData(\n        Number gasPrice_,\n        Number dataPrice_,\n        Number execBuffer_,\n        Number amortAttCost_,\n        Number etherPrice_,\n        Number markup_\n    ) internal pure returns (GasData) {\n        // Number type wraps uint16, so could safely be casted to uint96\n        // forgefmt: disable-next-item\n        return GasData.wrap(\n            uint96(Number.unwrap(gasPrice_)) \u003c\u003c SHIFT_GAS_PRICE |\n            uint96(Number.unwrap(dataPrice_)) \u003c\u003c SHIFT_DATA_PRICE |\n            uint96(Number.unwrap(execBuffer_)) \u003c\u003c SHIFT_EXEC_BUFFER |\n            uint96(Number.unwrap(amortAttCost_)) \u003c\u003c SHIFT_AMORT_ATT_COST |\n            uint96(Number.unwrap(etherPrice_)) \u003c\u003c SHIFT_ETHER_PRICE |\n            uint96(Number.unwrap(markup_))\n        );\n    }\n\n    /// @notice Wraps padded uint256 value into GasData struct.\n    function wrapGasData(uint256 paddedGasData) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(paddedGasData));\n    }\n\n    /// @notice Returns the gas price, in Wei per gas unit.\n    function gasPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_GAS_PRICE));\n    }\n\n    /// @notice Returns the calldata price, in Wei per byte of content.\n    function dataPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_DATA_PRICE));\n    }\n\n    /// @notice Returns the tx fee safety buffer for message execution, in Wei.\n    function execBuffer(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_EXEC_BUFFER));\n    }\n\n    /// @notice Returns the amortized cost for attestation submission, in Wei.\n    function amortAttCost(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_AMORT_ATT_COST));\n    }\n\n    /// @notice Returns the ratio of Chain's Ether Price / Mainnet Ether Price, in BWAD math.\n    function etherPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_ETHER_PRICE));\n    }\n\n    /// @notice Returns the markup for the message execution, in BWAD math.\n    function markup(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data)));\n    }\n\n    // ════════════════════════════════════════════════ CHAIN DATA ═════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded ChainGas struct with the given fields.\n    /// @param gasData_ Chain's gas data\n    /// @param domain_  Chain's domain\n    function encodeChainGas(GasData gasData_, uint32 domain_) internal pure returns (ChainGas) {\n        // GasData type wraps uint96, so could safely be casted to uint128\n        return ChainGas.wrap(uint128(GasData.unwrap(gasData_)) \u003c\u003c SHIFT_GAS_DATA | uint128(domain_));\n    }\n\n    /// @notice Wraps padded uint256 value into ChainGas struct.\n    function wrapChainGas(uint256 paddedChainGas) internal pure returns (ChainGas) {\n        // Casting to uint128 will truncate the highest bits, which is the behavior we want\n        return ChainGas.wrap(uint128(paddedChainGas));\n    }\n\n    /// @notice Returns the chain's gas data.\n    function gasData(ChainGas data) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(ChainGas.unwrap(data) \u003e\u003e SHIFT_GAS_DATA));\n    }\n\n    /// @notice Returns the chain's domain.\n    function domain(ChainGas data) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(ChainGas.unwrap(data));\n    }\n\n    /// @notice Returns the hash for the list of ChainGas structs.\n    function snapGasHash(ChainGas[] memory snapGas) internal pure returns (bytes32 snapGasHash_) {\n        // Use assembly to calculate the hash of the array without copying it\n        // ChainGas takes a single word of storage, thus ChainGas[] is stored in the following way:\n        // 0x00: length of the array, in words\n        // 0x20: first ChainGas struct\n        // 0x40: second ChainGas struct\n        // And so on...\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Find the location where the array data starts, we add 0x20 to skip the length field\n            let loc := add(snapGas, 0x20)\n            // Load the length of the array (in words).\n            // Shifting left 5 bits is equivalent to multiplying by 32: this converts from words to bytes.\n            let len := shl(5, mload(snapGas))\n            // Calculate the hash of the array\n            snapGasHash_ := keccak256(loc, len)\n        }\n    }\n}\n\n// contracts/libs/stack/Header.sol\n\n/// Header is encoded data with \"general routing information\".\ntype Header is uint136;\n\nusing HeaderLib for Header global;\n\n/// Types of messages supported by Origin-Destination\n/// - Base: message sent by protocol user, contains tips\n/// - Manager: message sent between AgentManager contracts located on different chains, no tips\nenum MessageFlag {\n    Base,\n    Manager\n}\n\nusing HeaderLib for MessageFlag global;\n\n/// Library for formatting _the header part_ of _the messages used by Origin and Destination_.\n/// - Header represents general information for routing a Message for Origin and Destination.\n/// - Header occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n///\n/// # Header stack layout (from highest bits to lowest)\n///\n/// | Position   | Field            | Type   | Bytes | Description                             |\n/// | ---------- | ---------------- | ------ | ----- | --------------------------------------- |\n/// | (017..016] | flag             | uint8  | 1     | Flag specifying the type of message     |\n/// | (016..012] | origin           | uint32 | 4     | Domain where message originated         |\n/// | (012..008] | nonce            | uint32 | 4     | Message nonce on the origin domain      |\n/// | (008..004] | destination      | uint32 | 4     | Domain where message will be executed   |\n/// | (004..000] | optimisticPeriod | uint32 | 4     | Optimistic period that will be enforced |\nlibrary HeaderLib {\n    /// @dev Amount of bits to shift to flag field\n    uint136 private constant SHIFT_FLAG = 16 * 8;\n    /// @dev Amount of bits to shift to origin field\n    uint136 private constant SHIFT_ORIGIN = 12 * 8;\n    /// @dev Amount of bits to shift to nonce field\n    uint136 private constant SHIFT_NONCE = 8 * 8;\n    /// @dev Amount of bits to shift to destination field\n    uint136 private constant SHIFT_DESTINATION = 4 * 8;\n\n    /// @notice Returns an encoded header with provided fields\n    /// @param origin_              Domain of origin chain\n    /// @param nonce_               Message nonce on origin chain\n    /// @param destination_         Domain of destination chain\n    /// @param optimisticPeriod_    Optimistic period for message execution\n    function encodeHeader(\n        MessageFlag flag_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint32 destination_,\n        uint32 optimisticPeriod_\n    ) internal pure returns (Header) {\n        // All casts below are upcasts, so they are safe\n        // forgefmt: disable-next-item\n        return Header.wrap(\n            uint136(uint8(flag_)) \u003c\u003c SHIFT_FLAG |\n            uint136(origin_) \u003c\u003c SHIFT_ORIGIN |\n            uint136(nonce_) \u003c\u003c SHIFT_NONCE |\n            uint136(destination_) \u003c\u003c SHIFT_DESTINATION |\n            uint136(optimisticPeriod_)\n        );\n    }\n\n    /// @notice Checks that the header is a valid encoded header.\n    function isHeader(uint256 paddedHeader) internal pure returns (bool) {\n        // Check that flag is within range\n        return _flag(paddedHeader) \u003c= uint8(type(MessageFlag).max);\n    }\n\n    /// @notice Wraps the padded encoded request into a Header-typed value.\n    /// @dev The \"padded\" header is simply an encoded header casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded headers\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedHeader) internal pure returns (Header) {\n        // Check that flag is within range\n        if (!isHeader(paddedHeader)) revert FlagOutOfRange();\n        // Casting to uint136 will truncate the highest bits, which is the behavior we want\n        return Header.wrap(uint136(paddedHeader));\n    }\n\n    /// @notice Returns header's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Header header) internal pure returns (bytes32 hashedHeader) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store header in scratch space\n            mstore(0, header)\n            // Compute hash of header padded to 32 bytes\n            hashedHeader := keccak256(0, 32)\n        }\n    }\n\n    // ══════════════════════════════════════════════ HEADER SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns header's flag field\n    function flag(Header header) internal pure returns (MessageFlag) {\n        // We check that flag is within range when wrapping the header, so this cast is safe\n        return MessageFlag(_flag(Header.unwrap(header)));\n    }\n\n    /// @notice Returns header's origin field\n    function origin(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_ORIGIN);\n    }\n\n    /// @notice Returns header's nonce field\n    function nonce(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_NONCE);\n    }\n\n    /// @notice Returns header's destination field\n    function destination(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_DESTINATION);\n    }\n\n    /// @notice Returns header's optimistic seconds field\n    function optimisticPeriod(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns header's flag field without casting to MessageFlag\n    function _flag(uint256 paddedHeader) private pure returns (uint8) {\n        // Casting to uint8 will truncate the highest bits, which is the behavior we want\n        return uint8(paddedHeader \u003e\u003e SHIFT_FLAG);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n     * constructor.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall \u0026\u0026 _initialized \u003c 1) || (!AddressUpgradeable.isContract(address(this)) \u0026\u0026 _initialized == 1),\n            \"Initializable: contract is already initialized\"\n        );\n        _initialized = 1;\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: setting the version to 255 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing \u0026\u0026 _initialized \u003c version, \"Initializable: contract is already initialized\");\n        _initialized = version;\n        _initializing = true;\n        _;\n        _initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        require(_initializing, \"Initializable: contract is not initializing\");\n        _;\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized != type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint8) {\n        return _initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _initializing;\n    }\n}\n\n// contracts/interfaces/IAgentManager.sol\n\ninterface IAgentManager {\n    /**\n     * @notice Allows Inbox to open a Dispute between a Guard and a Notary, if they are both not in Dispute already.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Guard or Notary is already in Dispute.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Allows Inbox to slash an agent, if their fraud was proven.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Domain doesn't match the saved agent domain.\n     * @param domain    Domain where the Agent is active\n     * @param agent     Address of the Agent\n     * @param prover    Address that initially provided fraud proof\n     */\n    function slashAgent(uint32 domain, address agent, address prover) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest known root of the Agent Merkle Tree.\n     */\n    function agentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns the number of opened Disputes.\n     * @dev This includes the Disputes that have been resolved already.\n     */\n    function getDisputesAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns information about the dispute with the given index.\n     * @dev Will revert if dispute with given index hasn't been opened yet.\n     * @param index             Dispute index\n     * @return guard            Address of the Guard in the Dispute\n     * @return notary           Address of the Notary in the Dispute\n     * @return slashedAgent     Address of the Agent who was slashed when Dispute was resolved\n     * @return fraudProver      Address who provided fraud proof to resolve the Dispute\n     * @return reportPayload    Raw payload with report data that led to the Dispute\n     * @return reportSignature  Guard signature for the report payload\n     */\n    function getDispute(uint256 index)\n        external\n        view\n        returns (\n            address guard,\n            address notary,\n            address slashedAgent,\n            address fraudProver,\n            bytes memory reportPayload,\n            bytes memory reportSignature\n        );\n\n    /**\n     * @notice Returns the current Dispute status of a given agent. See Structures.sol for details.\n     * @dev Every returned value will be set to zero if agent was not slashed and is not in Dispute.\n     * `rival` and `disputePtr` will be set to zero if the agent was slashed without being in Dispute.\n     * @param agent         Agent address\n     * @return flag         Flag describing the current Dispute status for the agent: None/Pending/Slashed\n     * @return rival        Address of the rival agent in the Dispute\n     * @return fraudProver  Address who provided fraud proof to resolve the Dispute\n     * @return disputePtr   Index of the opened Dispute PLUS ONE. Zero if agent is not in Dispute.\n     */\n    function disputeStatus(address agent)\n        external\n        view\n        returns (DisputeFlag flag, address rival, address fraudProver, uint256 disputePtr);\n}\n\n// contracts/interfaces/IAgentSecured.sol\n\ninterface IAgentSecured {\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * between a Guard and a Notary has been opened.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * has been resolved due to one of the agents being slashed.\n     * \u003e `rivalIndex` will be ZERO, if the slashed agent was not in the Dispute.\n     * @param slashedIndex  Index of the slashed agent in the Agent Merkle Tree\n     * @param rivalIndex    Index of the their Dispute Rival in the Agent Merkle Tree\n     */\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the address of the local AgentManager contract, which is treated as\n     * the \"source of truth\" for agent statuses.\n     */\n    function agentManager() external view returns (address);\n\n    /**\n     * @notice Returns the address of the local Inbox contract, which is treated as\n     * the \"source of truth\" for agent-signed statements.\n     * @dev Inbox passes verified agent statements to `IAgentSecured` contract.\n     */\n    function inbox() external view returns (address);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns (flag, openedAt, resolvedAt) that describes the latest status of\n     * the latest dispute for an agent with a given index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param agentIndex    Agent index in the Agent Merkle Tree\n     * @return              Latest dispute status for the given agent: (flag, openedAt, resolvedAt)\n     */\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory);\n}\n\n// contracts/libs/memory/ByteString.sol\n\n/// @dev CallData is a memory view over the payload to be used for an external call, i.e.\n/// recipient.call(callData). Its length is always (4 + 32 * N) bytes:\n/// - First 4 bytes represent the function selector.\n/// - 32 * N bytes represent N words that function arguments occupy.\ntype CallData is uint256;\n\n/// @dev Attach library functions to CallData\nusing ByteString for CallData global;\n\n/// @dev Signature is a memory view over a \"65 bytes\" array representing a ECDSA signature.\ntype Signature is uint256;\n\n/// @dev Attach library functions to Signature\nusing ByteString for Signature global;\n\nlibrary ByteString {\n    using MemViewLib for bytes;\n\n    /**\n     * @dev non-compact ECDSA signatures are enforced as of OZ 4.7.3\n     *\n     *      Signature payload memory layout\n     * [000 .. 032) r   bytes32 32 bytes\n     * [032 .. 064) s   bytes32 32 bytes\n     * [064 .. 065) v   uint8    1 byte\n     */\n    uint256 internal constant SIGNATURE_LENGTH = 65;\n    uint256 private constant OFFSET_R = 0;\n    uint256 private constant OFFSET_S = 32;\n    uint256 private constant OFFSET_V = 64;\n\n    /**\n     * @dev Calldata memory layout\n     * [000 .. 004) selector    bytes4  4 bytes\n     *      Optional: N function arguments\n     * [004 .. 036) arg1        bytes32 32 bytes\n     *      ..\n     * [AAA .. END) argN        bytes32 32 bytes\n     */\n    uint256 internal constant SELECTOR_LENGTH = 4;\n    uint256 private constant OFFSET_SELECTOR = 0;\n    uint256 private constant OFFSET_ARGUMENTS = SELECTOR_LENGTH;\n\n    // ═════════════════════════════════════════════════ SIGNATURE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the signature payload from the given values.\n     * @dev Using ByteString.formatSignature({r: r, s: s, v: v}) will make sure\n     * that params are given in the right order.\n     */\n    function formatSignature(bytes32 r, bytes32 s, uint8 v) internal pure returns (bytes memory) {\n        return abi.encodePacked(r, s, v);\n    }\n\n    /**\n     * @notice Returns a Signature view over for the given payload.\n     * @dev Will revert if the payload is not a signature.\n     */\n    function castToSignature(bytes memory payload) internal pure returns (Signature) {\n        return castToSignature(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Signature view.\n     * @dev Will revert if the memory view is not over a signature.\n     */\n    function castToSignature(MemView memView) internal pure returns (Signature) {\n        if (!isSignature(memView)) revert UnformattedSignature();\n        return Signature.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a signature\n     */\n    function isSignature(MemView memView) internal pure returns (bool) {\n        return memView.len() == SIGNATURE_LENGTH;\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Signature signature) internal pure returns (MemView) {\n        return MemView.wrap(Signature.unwrap(signature));\n    }\n\n    // ═════════════════════════════════════════════ SIGNATURE SLICING ═════════════════════════════════════════════════\n\n    /// @notice Unpacks signature payload into (r, s, v) parameters.\n    /// @dev Make sure to verify signature length with isSignature() beforehand.\n    function toRSV(Signature signature) internal pure returns (bytes32 r, bytes32 s, uint8 v) {\n        // Get the underlying memory view\n        MemView memView = unwrap(signature);\n        r = memView.index({index_: OFFSET_R, bytes_: 32});\n        s = memView.index({index_: OFFSET_S, bytes_: 32});\n        // Can be safely casted to uint8, since we index a single byte\n        v = uint8(memView.indexUint({index_: OFFSET_V, bytes_: 1}));\n    }\n\n    // ═════════════════════════════════════════════════ CALLDATA ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the calldata with the modified arguments:\n     * the existing arguments are prepended with the arguments from the prefix.\n     * @dev Given:\n     *  - `calldata = abi.encodeWithSelector(foo.selector, d, e);`\n     *  - `prefix = abi.encode(a, b, c);`\n     *  - `a`, `b`, `c` are arguments of static type (i.e. not dynamically sized ones)\n     *      Then:\n     *  - Function will return abi.encodeWithSelector(foo.selector, a, c, c, d, e)\n     *  - Returned calldata will trigger `foo(a, b, c, d, e)` when used for a contract call.\n     * Note: for clarification as to what types are considered static, see\n     * https://docs.soliditylang.org/en/latest/abi-spec.html#formal-specification-of-the-encoding\n     * @param callData  Calldata that needs to be modified\n     * @param prefix    ABI-encoded arguments to use as the first arguments in the new calldata\n     * @return Modified calldata having prefix as the first arguments.\n     */\n    function addPrefix(CallData callData, bytes memory prefix) internal view returns (bytes memory) {\n        // Prefix should occupy a whole amount of words in memory\n        if (!_fullWords(prefix.length)) revert UnformattedCallDataPrefix();\n        MemView[] memory views = new MemView[](3);\n        // Use payload's function selector\n        views[0] = abi.encodePacked(callData.callSelector()).ref();\n        // Use prefix as the first arguments\n        views[1] = prefix.ref();\n        // Use payload's remaining arguments\n        views[2] = callData.arguments();\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a CallData view over for the given payload.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(bytes memory payload) internal pure returns (CallData) {\n        return castToCallData(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a CallData view.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(MemView memView) internal pure returns (CallData) {\n        if (!isCallData(memView)) revert UnformattedCallData();\n        return CallData.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a valid calldata, i.e.\n     * a function selector, followed by arbitrary amount of arguments.\n     */\n    function isCallData(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Calldata should at least have a function selector\n        if (length \u003c SELECTOR_LENGTH) return false;\n        // The remainder of the calldata should be exactly N memory words (N \u003e= 0)\n        return _fullWords(length - SELECTOR_LENGTH);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(CallData callData) internal pure returns (MemView) {\n        return MemView.wrap(CallData.unwrap(callData));\n    }\n\n    /// @notice Returns callData's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(CallData callData) internal pure returns (bytes32) {\n        return callData.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ CALLDATA SLICING ══════════════════════════════════════════════════\n\n    /**\n     * @notice Returns amount of memory words (32 byte chunks) the function arguments\n     * occupy in the calldata.\n     * @dev This might differ from amount of arguments supplied, if any of the arguments\n     * occupies more than one memory slot. It is true, however, that argument part of the payload\n     * occupies exactly N words, even for dynamic types like `bytes`\n     */\n    function argumentWords(CallData callData) internal pure returns (uint256) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        // Equivalent of (length - SELECTOR_LENGTH) / 32\n        return (memView.len() - SELECTOR_LENGTH) \u003e\u003e 5;\n    }\n\n    /// @notice Returns selector for the provided calldata.\n    function callSelector(CallData callData) internal pure returns (bytes4) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return bytes4(memView.index({index_: OFFSET_SELECTOR, bytes_: SELECTOR_LENGTH}));\n    }\n\n    /// @notice Returns abi encoded arguments for the provided calldata.\n    function arguments(CallData callData) internal pure returns (MemView) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return memView.sliceFrom({index_: OFFSET_ARGUMENTS});\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if length is full amount of memory words (32 bytes).\n    function _fullWords(uint256 length) internal pure returns (bool) {\n        // The equivalent of length % 32 == 0\n        return length \u0026 31 == 0;\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n    function __Context_init() internal onlyInitializing {\n    }\n\n    function __Context_init_unchained() internal onlyInitializing {\n    }\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[50] private __gap;\n}\n\n// contracts/libs/merkle/MerkleTree.sol\n\n/// `BaseTree` is a struct representing incremental merkle tree.\n/// - Contains only the current branch.\n/// - The number of inserted leaves is stored externally, and is later supplied for tree operations.\n/// - Has a fixed height of `ORIGIN_TREE_HEIGHT`.\n/// - Can store up to `2 ** ORIGIN_TREE_HEIGHT - 1` leaves.\n/// \u003e Note: the hash function for the tree `H(x, y)` is defined as:\n/// \u003e - `H(0,0) = 0`\n/// \u003e - `H(x,y) = keccak256(x, y), when (x != 0 || y != 0)`\n/// ## Invariant for leafs\n/// - The leftmost empty leaf has `index == count`, where `count` is the amount of the inserted leafs so far.\n/// - Value for any empty leaf or node is bytes32(0).\n/// ## Invariant for current branch\n/// `branch[i]` is always the value of a node on the i-th level.\n/// Levels are numbered from leafs to root: `0 .. ORIGIN_TREE_HEIGHT`.\n/// `branch[i]` stores the value for the node, such that:\n//  - The node is a \"left child\" (e.g. has an even index).\n/// - The node must have two non-empty children.\n/// - Out of all level's \"left child\" nodes with \"non-empty children\",\n/// the one with the biggest index (the rightmost one) is stored as `branch[i]`.\n/// \u003e __`branch` could be used to form a proof of inclusion for the first empty leaf (`index == count`).__\n/// _Here is how:_\n/// - Let's walk along the path from the \"first empty leaf\" to the root.\n/// - i-th bit of the \"first empty leaf\" index (which is equal to `count`) determines if the path's node\n/// for this i-th level is a \"left child\" or a \"right child\".\n/// - i-th bit in `count` is 0 → we are the left child on this level → sibling is the right child\n/// that does not exist yet → `proof[i] = bytes32(0)`.\n/// - i-th bit in `count` is 1 → we are the right child on this level → sibling is the left child\n/// sibling is the rightmost \"left child\" node on the level → `proof[i] = branch[i]`.\n/// \u003e Therefore `proof[i] = (count \u0026 (1 \u003c\u003c i)) == 0 ? bytes32(0) : branch[i])`\nstruct BaseTree {\n    bytes32[ORIGIN_TREE_HEIGHT] branch;\n}\n\nusing MerkleTree for BaseTree global;\n\n/// `HistoricalTree` is an incremental merkle tree keeping track of its historical merkle roots.\n/// \u003e - `roots[N]` is the root of the tree after `N` leafs were inserted\n/// \u003e - `roots[0] == bytes32(0)`\n/// @param tree     Incremental merkle tree\n/// @param roots    Historical merkle roots of the tree\nstruct HistoricalTree {\n    BaseTree tree;\n    bytes32[] roots;\n}\n\nusing MerkleTree for HistoricalTree global;\n\n/// `DynamicTree` is a struct representing a Merkle Tree with `2**AGENT_TREE_HEIGHT` leaves.\n/// - A single operation is available: update value for leaf with an arbitrary index (which might be a non-empty leaf).\n/// - This is done by requesting the proof of inclusion for the old value, which is used to both\n/// verify the old value, and calculate the new root.\n/// \u003e Based on Original idea from [ER forum post](https://ethresear.ch/t/efficient-on-chain-dynamic-merkle-tree/11054).\nstruct DynamicTree {\n    bytes32 root;\n}\n\nusing MerkleTree for DynamicTree global;\n\n/// MerkleTree is work based on Nomad's Merkle.sol, which is used under MIT OR Apache-2.0\n/// [link](https://github.com/nomad-xyz/monorepo/blob/main/packages/contracts-core/contracts/libs/Merkle.sol).\n/// With the following changes:\n/// - Adapted for Solidity 0.8.x.\n/// - Amount of tree leaves stored externally.\n/// - Added thorough documentation.\n/// - `H(0,0) = 0` optimization from [ER forum post](https://ethresear.ch/t/optimizing-sparse-merkle-trees/3751/6).\n/// \u003e Nomad's Merkle.sol is work based on eth2 deposit contract, which is used under CC0-1.0\n///[link](https://github.com/ethereum/deposit_contract/blob/dev/deposit_contract/contracts/validator_registration.v.py).\n/// With the following changes:\n/// \u003e - Implemented in Solidity 0.7.6 (eth2 deposit contract implemented in Vyper).\n/// \u003e - `H() = keccak256()` is used as the hashing function instead of `sha256()`.\nlibrary MerkleTree {\n    /// @dev For root calculation we need at least one empty leaf, thus the minus one in the formula.\n    uint256 internal constant MAX_LEAVES = 2 ** ORIGIN_TREE_HEIGHT - 1;\n\n    // ═════════════════════════════════════════════════ BASE TREE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Inserts `node` into merkle tree\n     * @dev Reverts if tree is full\n     * @param newCount  Amount of inserted leaves in the tree after the insertion (i.e. current + 1)\n     * @param node      Element to insert into tree\n     */\n    function insertBase(BaseTree storage tree, uint256 newCount, bytes32 node) internal {\n        if (newCount \u003e MAX_LEAVES) revert MerkleTreeFull();\n        // We go up the tree following the branch from the empty leaf AFTER the just inserted one.\n        // We stop when we find the first \"right child\" node.\n        // Its sibling is now the rightmost \"left child\" node that has two non-empty children.\n        // Therefore we need to update `tree.branch` value on this level.\n        // One could see that `tree.branch` value on lower and higher levels remain unchanged.\n\n        // Loop invariant: `node` is the current level's value for the branch from JUST INSERTED leaf\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            if ((newCount \u0026 1) == 1) {\n                // Found the first \"right child\" node on the branch from EMPTY leaf\n                // `node` is the value for node on branch from JUST INSERTED leaf\n                // Which in this case is the \"left child\".\n                // We update tree.branch and exit\n                tree.branch[i] = node;\n                return;\n            }\n            // On the branch from EMPTY leaf this is still a \"left child\".\n            // Meaning on branch from JUST INSERTED leaf, `node` is a right child.\n            // We compute value for `node` parent using `tree.branch` invariant:\n            // This is the rightmost \"left child\" node, which would be sibling of `node`.\n            node = MerkleMath.getParent(tree.branch[i], node);\n            // Get the parent index, and go to the next tree level\n            newCount \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n        // As the loop should always end prematurely with the `return` statement,\n        // this code should be unreachable. We assert `false` just to be safe.\n        assert(false);\n    }\n\n    /**\n     * @notice Calculates and returns current root of the merkle tree.\n     * @param count     Current amount of inserted leaves in the tree\n     * @return current  Calculated root of `tree`\n     */\n    function rootBase(BaseTree storage tree, uint256 count) internal view returns (bytes32 current) {\n        // To calculate the root we follow the branch of first EMPTY leaf (index == count)\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            // Check if we are the left or the right child on the current level\n            if ((count \u0026 1) == 1) {\n                // We are the right child. Our sibling is the \"rightmost\" \"left-child\" node\n                // that has two non-empty children → sibling is `tree.branch[i]`\n                current = MerkleMath.getParent(tree.branch[i], current);\n            } else {\n                // We are the left child. Our sibling does not exist yet → sibling is EMPTY\n                current = MerkleMath.getParent(current, bytes32(0));\n            }\n            // Get the parent index, and go to the next tree level\n            count \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    // ══════════════════════════════════════════════ HISTORICAL TREE ══════════════════════════════════════════════════\n\n    /// @notice Initializes the historical roots for the tree by inserting an empty root.\n    // solhint-disable-next-line ordering\n    function initializeRoots(HistoricalTree storage tree) internal returns (bytes32 savedRoot) {\n        // This should only be called once, when the contract is initialized\n        assert(tree.roots.length == 0);\n        // Save root for empty merkle tree: bytes32(0)\n        tree.roots.push(savedRoot);\n    }\n\n    /// @notice Inserts a new leaf into the merkle tree.\n    /// @dev Reverts if tree is full.\n    /// @param node         Element to insert into tree\n    /// @return newRoot     Merkle root after the leaf was inserted\n    function insert(HistoricalTree storage tree, bytes32 node) internal returns (bytes32 newRoot) {\n        // Tree count after the new leaf will be inserted (we store roots[0] as root of empty tree)\n        uint256 newCount = tree.roots.length;\n        tree.tree.insertBase(newCount, node);\n        // Save the new root\n        newRoot = tree.tree.rootBase(newCount);\n        tree.roots.push(newRoot);\n    }\n\n    /// @notice Returns the historical root of the merkle tree.\n    /// @dev Reverts if not enough leafs have been inserted.\n    /// @param count            Amount of leafs in the tree at some point of time\n    /// @return historicalRoot  Merkle root after `count` leafs were inserted\n    function root(HistoricalTree storage tree, uint256 count) internal view returns (bytes32 historicalRoot) {\n        if (count \u003e= tree.roots.length) revert NotEnoughLeafs();\n        return tree.roots[count];\n    }\n\n    // ═══════════════════════════════════════════════ DYNAMIC TREE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Updates the value for the leaf with the given index in the Dynamic Merkle Tree.\n     * @dev Will revert if incorrect proof of inclusion for old value is supplied.\n     * @param tree          Dynamic merkle tree\n     * @param index         Index of the leaf to update\n     * @param oldValue      Previous value of the leaf\n     * @param branch        Proof of inclusion of previous value into the tree\n     * @param newValue      New leaf value to assign\n     * @return newRoot      New value for the Merkle Root after the leaf is updated\n     */\n    function update(\n        DynamicTree storage tree,\n        uint256 index,\n        bytes32 oldValue,\n        bytes32[] memory branch,\n        bytes32 newValue\n    ) internal returns (bytes32 newRoot) {\n        // Check that the old value + proof result in a correct root\n        if (MerkleMath.proofRoot(index, oldValue, branch, AGENT_TREE_HEIGHT) != tree.root) {\n            revert LeafNotProven();\n        }\n        // New root is new value + the same proof (values for sibling nodes are not updated)\n        newRoot = MerkleMath.proofRoot(index, newValue, branch, AGENT_TREE_HEIGHT);\n        // Write the new root\n        tree.root = newRoot;\n    }\n}\n\n// contracts/libs/stack/Tips.sol\n\n/// Tips is encoded data with \"tips paid for sending a base message\".\n/// Note: even though uint256 is also an underlying type for MemView, Tips is stored ON STACK.\ntype Tips is uint256;\n\nusing TipsLib for Tips global;\n\n/// # Tips\n/// Library for formatting _the tips part_ of _the base messages_.\n///\n/// ## How the tips are awarded\n/// Tips are paid for sending a base message, and are split across all the agents that\n/// made the message execution on destination chain possible.\n/// ### Summit tips\n/// Split between:\n///     - Guard posting a snapshot with state ST_G for the origin chain.\n///     - Notary posting a snapshot SN_N using ST_G. This creates attestation A.\n///     - Notary posting a message receipt after it is executed on destination chain.\n/// ### Attestation tips\n/// Paid to:\n///     - Notary posting attestation A to destination chain.\n/// ### Execution tips\n/// Paid to:\n///     - First executor performing a valid execution attempt (correct proofs, optimistic period over),\n///      using attestation A to prove message inclusion on origin chain, whether the recipient reverted or not.\n/// ### Delivery tips.\n/// Paid to:\n///     - Executor who successfully executed the message on destination chain.\n///\n/// ## Tips encoding\n/// - Tips occupy a single storage word, and thus are stored on stack instead of being stored in memory.\n/// - The actual tip values should be determined by multiplying stored values by divided by TIPS_MULTIPLIER=2**32.\n/// - Tips are packed into a single word of storage, while allowing real values up to ~8*10**28 for every tip category.\n/// \u003e The only downside is that the \"real tip values\" are now multiplies of ~4*10**9, which should be fine even for\n/// the chains with the most expensive gas currency.\n/// # Tips stack layout (from highest bits to lowest)\n///\n/// | Position   | Field          | Type   | Bytes | Description                                                |\n/// | ---------- | -------------- | ------ | ----- | ---------------------------------------------------------- |\n/// | (032..024] | summitTip      | uint64 | 8     | Tip for agents interacting with Summit contract            |\n/// | (024..016] | attestationTip | uint64 | 8     | Tip for Notary posting attestation to Destination contract |\n/// | (016..008] | executionTip   | uint64 | 8     | Tip for valid execution attempt on destination chain       |\n/// | (008..000] | deliveryTip    | uint64 | 8     | Tip for successful message delivery on destination chain   |\n\nlibrary TipsLib {\n    using SafeCast for uint256;\n\n    /// @dev Amount of bits to shift to summitTip field\n    uint256 private constant SHIFT_SUMMIT_TIP = 24 * 8;\n    /// @dev Amount of bits to shift to attestationTip field\n    uint256 private constant SHIFT_ATTESTATION_TIP = 16 * 8;\n    /// @dev Amount of bits to shift to executionTip field\n    uint256 private constant SHIFT_EXECUTION_TIP = 8 * 8;\n\n    // ═══════════════════════════════════════════════════ TIPS ════════════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips with the given fields\n    /// @param summitTip_        Tip for agents interacting with Summit contract, divided by TIPS_MULTIPLIER\n    /// @param attestationTip_   Tip for Notary posting attestation to Destination contract, divided by TIPS_MULTIPLIER\n    /// @param executionTip_     Tip for valid execution attempt on destination chain, divided by TIPS_MULTIPLIER\n    /// @param deliveryTip_      Tip for successful message delivery on destination chain, divided by TIPS_MULTIPLIER\n    function encodeTips(uint64 summitTip_, uint64 attestationTip_, uint64 executionTip_, uint64 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // forgefmt: disable-next-item\n        return Tips.wrap(\n            uint256(summitTip_) \u003c\u003c SHIFT_SUMMIT_TIP |\n            uint256(attestationTip_) \u003c\u003c SHIFT_ATTESTATION_TIP |\n            uint256(executionTip_) \u003c\u003c SHIFT_EXECUTION_TIP |\n            uint256(deliveryTip_)\n        );\n    }\n\n    /// @notice Convenience function to encode tips with uint256 values.\n    function encodeTips256(uint256 summitTip_, uint256 attestationTip_, uint256 executionTip_, uint256 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // In practice, the tips amounts are not supposed to be higher than 2**96, and with 32 bits of granularity\n        // using uint64 is enough to store the values. However, we still check for overflow just in case.\n        // TODO: consider using Number type to store the tips values.\n        return encodeTips({\n            summitTip_: (summitTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            attestationTip_: (attestationTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            executionTip_: (executionTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            deliveryTip_: (deliveryTip_ \u003e\u003e TIPS_GRANULARITY).toUint64()\n        });\n    }\n\n    /// @notice Wraps the padded encoded tips into a Tips-typed value.\n    /// @dev There is no actual padding here, as the underlying type is already uint256,\n    /// but we include this function for consistency and to be future-proof, if tips will eventually use anything\n    /// smaller than uint256.\n    function wrapPadded(uint256 paddedTips) internal pure returns (Tips) {\n        return Tips.wrap(paddedTips);\n    }\n\n    /**\n     * @notice Returns a formatted Tips payload specifying empty tips.\n     * @return Formatted tips\n     */\n    function emptyTips() internal pure returns (Tips) {\n        return Tips.wrap(0);\n    }\n\n    /// @notice Returns tips's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Tips tips) internal pure returns (bytes32 hashedTips) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store tips in scratch space\n            mstore(0, tips)\n            // Compute hash of tips padded to 32 bytes\n            hashedTips := keccak256(0, 32)\n        }\n    }\n\n    // ═══════════════════════════════════════════════ TIPS SLICING ════════════════════════════════════════════════════\n\n    /// @notice Returns summitTip field\n    function summitTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_SUMMIT_TIP);\n    }\n\n    /// @notice Returns attestationTip field\n    function attestationTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_ATTESTATION_TIP);\n    }\n\n    /// @notice Returns executionTip field\n    function executionTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_EXECUTION_TIP);\n    }\n\n    /// @notice Returns deliveryTip field\n    function deliveryTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips));\n    }\n\n    // ════════════════════════════════════════════════ TIPS VALUE ═════════════════════════════════════════════════════\n\n    /// @notice Returns total value of the tips payload.\n    /// This is the sum of the encoded values, scaled up by TIPS_MULTIPLIER\n    function value(Tips tips) internal pure returns (uint256 value_) {\n        value_ = uint256(tips.summitTip()) + tips.attestationTip() + tips.executionTip() + tips.deliveryTip();\n        value_ \u003c\u003c= TIPS_GRANULARITY;\n    }\n\n    /// @notice Increases the delivery tip to match the new value.\n    function matchValue(Tips tips, uint256 newValue) internal pure returns (Tips newTips) {\n        uint256 oldValue = tips.value();\n        if (newValue \u003c oldValue) revert TipsValueTooLow();\n        // We want to increase the delivery tip, while keeping the other tips the same\n        unchecked {\n            uint256 delta = (newValue - oldValue) \u003e\u003e TIPS_GRANULARITY;\n            // `delta` fits into uint224, as TIPS_GRANULARITY is 32, so this never overflows uint256.\n            // In practice, this will never overflow uint64 as well, but we still check it just in case.\n            if (delta + tips.deliveryTip() \u003e type(uint64).max) revert TipsOverflow();\n            // Delivery tips occupy lowest 8 bytes, so we can just add delta to the tips value\n            // to effectively increase the delivery tip (knowing that delta fits into uint64).\n            newTips = Tips.wrap(Tips.unwrap(tips) + delta);\n        }\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    function __Ownable_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable_init_unchained() internal onlyInitializing {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n    function __Ownable2Step_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable2Step_init_unchained() internal onlyInitializing {\n    }\n    address private _pendingOwner;\n\n    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Returns the address of the pending owner.\n     */\n    function pendingOwner() public view virtual returns (address) {\n        return _pendingOwner;\n    }\n\n    /**\n     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual override onlyOwner {\n        _pendingOwner = newOwner;\n        emit OwnershipTransferStarted(owner(), newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual override {\n        delete _pendingOwner;\n        super._transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev The new owner accepts the ownership transfer.\n     */\n    function acceptOwnership() public virtual {\n        address sender = _msgSender();\n        require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n        _transferOwnership(sender);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// contracts/libs/memory/State.sol\n\n/// State is a memory view over a formatted state payload.\ntype State is uint256;\n\nusing StateLib for State global;\n\n/// # State\n/// State structure represents the state of Origin contract at some point of time.\n/// - State is structured in a way to track the updates of the Origin Merkle Tree.\n/// - State includes root of the Origin Merkle Tree, origin domain and some additional metadata.\n/// ## Origin Merkle Tree\n/// Hash of every sent message is inserted in the Origin Merkle Tree, which changes\n/// the value of Origin Merkle Root (which is the root for the mentioned tree).\n/// - Origin has a single Merkle Tree for all messages, regardless of their destination domain.\n/// - This leads to Origin state being updated if and only if a message was sent in a block.\n/// - Origin contract is a \"source of truth\" for states: a state is considered \"valid\" in its Origin,\n/// if it matches the state of the Origin contract after the N-th (nonce) message was sent.\n///\n/// # Memory layout of State fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                    |\n/// | ---------- | ----------- | ------- | ----- | ------------------------------ |\n/// | [000..032) | root        | bytes32 | 32    | Root of the Origin Merkle Tree |\n/// | [032..036) | origin      | uint32  | 4     | Domain where Origin is located |\n/// | [036..040) | nonce       | uint32  | 4     | Amount of sent messages        |\n/// | [040..045) | blockNumber | uint40  | 5     | Block of last sent message     |\n/// | [045..050) | timestamp   | uint40  | 5     | Time of last sent message      |\n/// | [050..062) | gasData     | uint96  | 12    | Gas data for the chain         |\n///\n/// @dev State could be used to form a Snapshot to be signed by a Guard or a Notary.\nlibrary StateLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_ROOT = 0;\n    uint256 private constant OFFSET_ORIGIN = 32;\n    uint256 private constant OFFSET_NONCE = 36;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 40;\n    uint256 private constant OFFSET_TIMESTAMP = 45;\n    uint256 private constant OFFSET_GAS_DATA = 50;\n\n    // ═══════════════════════════════════════════════════ STATE ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted State payload with provided fields\n     * @param root_         New merkle root\n     * @param origin_       Domain of Origin's chain\n     * @param nonce_        Nonce of the merkle root\n     * @param blockNumber_  Block number when root was saved in Origin\n     * @param timestamp_    Block timestamp when root was saved in Origin\n     * @param gasData_      Gas data for the chain\n     * @return Formatted state\n     */\n    function formatState(\n        bytes32 root_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_,\n        GasData gasData_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(root_, origin_, nonce_, blockNumber_, timestamp_, gasData_);\n    }\n\n    /**\n     * @notice Returns a State view over the given payload.\n     * @dev Will revert if the payload is not a state.\n     */\n    function castToState(bytes memory payload) internal pure returns (State) {\n        return castToState(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a State view.\n     * @dev Will revert if the memory view is not over a state.\n     */\n    function castToState(MemView memView) internal pure returns (State) {\n        if (!isState(memView)) revert UnformattedState();\n        return State.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted State.\n    function isState(MemView memView) internal pure returns (bool) {\n        return memView.len() == STATE_LENGTH;\n    }\n\n    /// @notice Returns the hash of a State, that could be later signed by a Guard to signal\n    /// that the state is invalid.\n    function hashInvalid(State state) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(stateInvalidSalt, keccak(state))\n        return state.unwrap().keccakSalted(STATE_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(State state) internal pure returns (MemView) {\n        return MemView.wrap(State.unwrap(state));\n    }\n\n    /// @notice Compares two State structures.\n    function equals(State a, State b) internal pure returns (bool) {\n        // Length of a State payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═══════════════════════════════════════════════ STATE HASHING ═══════════════════════════════════════════════════\n\n    /// @notice Returns the hash of the State.\n    /// @dev We are using the Merkle Root of a tree with two leafs (see below) as state hash.\n    function leaf(State state) internal pure returns (bytes32) {\n        (bytes32 leftLeaf_, bytes32 rightLeaf_) = state.subLeafs();\n        // Final hash is the parent of these leafs\n        return keccak256(bytes.concat(leftLeaf_, rightLeaf_));\n    }\n\n    /// @notice Returns \"sub-leafs\" of the State. Hash of these \"sub leafs\" is going to be used\n    /// as a \"state leaf\" in the \"Snapshot Merkle Tree\".\n    /// This enables proving that leftLeaf = (root, origin) was a part of the \"Snapshot Merkle Tree\",\n    /// by combining `rightLeaf` with the remainder of the \"Snapshot Merkle Proof\".\n    function subLeafs(State state) internal pure returns (bytes32 leftLeaf_, bytes32 rightLeaf_) {\n        MemView memView = state.unwrap();\n        // Left leaf is (root, origin)\n        leftLeaf_ = memView.prefix({len_: OFFSET_NONCE}).keccak();\n        // Right leaf is (metadata), or (nonce, blockNumber, timestamp)\n        rightLeaf_ = memView.sliceFrom({index_: OFFSET_NONCE}).keccak();\n    }\n\n    /// @notice Returns the left \"sub-leaf\" of the State.\n    function leftLeaf(bytes32 root_, uint32 origin_) internal pure returns (bytes32) {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(root_, origin_));\n    }\n\n    /// @notice Returns the right \"sub-leaf\" of the State.\n    function rightLeaf(uint32 nonce_, uint40 blockNumber_, uint40 timestamp_, GasData gasData_)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(nonce_, blockNumber_, timestamp_, gasData_));\n    }\n\n    // ═══════════════════════════════════════════════ STATE SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns a historical Merkle root from the Origin contract.\n    function root(State state) internal pure returns (bytes32) {\n        return state.unwrap().index({index_: OFFSET_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns domain of chain where the Origin contract is deployed.\n    function origin(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns nonce of Origin contract at the time, when `root` was the Merkle root.\n    function nonce(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when `root` was saved in Origin.\n    function blockNumber(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when `root` was saved in Origin.\n    /// @dev This is the timestamp according to the origin chain.\n    function timestamp(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n\n    /// @notice Returns gas data for the chain.\n    function gasData(State state) internal pure returns (GasData) {\n        return GasDataLib.wrapGasData(state.unwrap().indexUint({index_: OFFSET_GAS_DATA, bytes_: GAS_DATA_LENGTH}));\n    }\n}\n\n// contracts/libs/memory/BaseMessage.sol\n\n/// BaseMessage is a memory view over the base message supported by Origin-Destination\ntype BaseMessage is uint256;\n\nusing BaseMessageLib for BaseMessage global;\n\n/// BaseMessage structure represents a base message sent via the Origin-Destination contracts.\n/// - It only contains data relevant to the base message, the rest of data is encoded in the message header.\n/// - `sender` and `recipient` for EVM chains are EVM addresses casted to bytes32, while preserving left-alignment.\n/// - `tips` and `request` parameters are specified by a message sender\n/// \u003e Origin will calculate minimum tips for given request and content length, and will reject messages with tips\n/// lower than that.\n///\n/// # Memory layout of BaseMessage fields\n///\n/// | Position   | Field     | Type    | Bytes | Description                            |\n/// | ---------- | --------- | ------- | ----- | -------------------------------------- |\n/// | [000..032) | tips      | uint256 | 32    | Encoded tips paid on origin chain      |\n/// | [032..064) | sender    | bytes32 | 32    | Sender address on origin chain         |\n/// | [064..096) | recipient | bytes32 | 32    | Recipient address on destination chain |\n/// | [096..116) | request   | uint160 | 20    | Encoded request for message execution  |\n/// | [104..AAA) | content   | bytes   | ??    | Content to be passed to recipient      |\nlibrary BaseMessageLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_TIPS = 0;\n    uint256 private constant OFFSET_SENDER = 32;\n    uint256 private constant OFFSET_RECIPIENT = 64;\n    uint256 private constant OFFSET_REQUEST = OFFSET_RECIPIENT + TIPS_LENGTH;\n    uint256 private constant OFFSET_CONTENT = OFFSET_REQUEST + REQUEST_LENGTH;\n\n    // ═══════════════════════════════════════════════ BASE MESSAGE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted BaseMessage payload with provided fields.\n     * @param tips_         Encoded tips information\n     * @param sender_       Sender address on origin chain\n     * @param recipient_    Recipient address on destination chain\n     * @param request_      Encoded request for message execution\n     * @param content_      Raw content to be passed to recipient on destination chain\n     * @return Formatted base message\n     */\n    function formatBaseMessage(Tips tips_, bytes32 sender_, bytes32 recipient_, Request request_, bytes memory content_)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return abi.encodePacked(tips_, sender_, recipient_, request_, content_);\n    }\n\n    /**\n     * @notice Returns a BaseMessage view over the given payload.\n     * @dev Will revert if the payload is not a base message.\n     */\n    function castToBaseMessage(bytes memory payload) internal pure returns (BaseMessage) {\n        return castToBaseMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a BaseMessage view.\n     * @dev Will revert if the memory view is not over a base message payload.\n     */\n    function castToBaseMessage(MemView memView) internal pure returns (BaseMessage) {\n        if (!isBaseMessage(memView)) revert UnformattedBaseMessage();\n        return BaseMessage.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted BaseMessage.\n    function isBaseMessage(MemView memView) internal pure returns (bool) {\n        // Check if sender, recipient, tips fields exist\n        return (memView.len() \u003e= OFFSET_CONTENT);\n        // Content could be empty, so we don't check that\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(BaseMessage baseMessage) internal pure returns (MemView) {\n        return MemView.wrap(BaseMessage.unwrap(baseMessage));\n    }\n\n    /// @notice Returns baseMessage's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        // We hash \"tips\" and \"everything but tips\" to make tips proofs easier to verify\n        return MerkleMath.getParent(baseMessage.tips().leaf(), baseMessage.bodyLeaf());\n    }\n\n    /// @notice Returns hash for the \"everything but tips\" part of the base message.\n    function bodyLeaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_SENDER}).keccak();\n    }\n\n    // ═══════════════════════════════════════════ BASE MESSAGE SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips paid on origin chain.\n    function tips(BaseMessage baseMessage) internal pure returns (Tips) {\n        return TipsLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_TIPS, bytes_: TIPS_LENGTH})));\n    }\n\n    /// @notice Returns sender address on origin chain.\n    function sender(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_SENDER, bytes_: 32});\n    }\n\n    /// @notice Returns recipient address on destination chain.\n    function recipient(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_RECIPIENT, bytes_: 32});\n    }\n\n    /// @notice Returns an encoded request for message execution on destination chain.\n    function request(BaseMessage baseMessage) internal pure returns (Request) {\n        return RequestLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_REQUEST, bytes_: REQUEST_LENGTH})));\n    }\n\n    /// @notice Returns an untyped memory view over the content to be passed to recipient.\n    function content(BaseMessage baseMessage) internal pure returns (MemView) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_CONTENT});\n    }\n}\n\n// contracts/base/MessagingBase.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for all messaging contracts.\n * - Provides context on the local chain's domain.\n * - Provides ownership functionality.\n * - Will be providing pausing functionality when it is implemented.\n */\nabstract contract MessagingBase is MultiCallable, Versioned, Ownable2StepUpgradeable {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @notice Domain of the local chain, set once upon contract creation\n    uint32 public immutable localDomain;\n    // @notice Domain of the Synapse chain, set once upon contract creation\n    uint32 public immutable synapseDomain;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev gap for upgrade safety\n    uint256[50] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    constructor(string memory version_, uint32 synapseDomain_) Versioned(version_) {\n        localDomain = ChainContext.chainId();\n        synapseDomain = synapseDomain_;\n    }\n\n    // TODO: Implement pausing\n\n    /**\n     * @dev Should be impossible to renounce ownership;\n     * we override OpenZeppelin OwnableUpgradeable's\n     * implementation of renounceOwnership to make it a no-op\n     */\n    function renounceOwnership() public override onlyOwner {} //solhint-disable-line no-empty-blocks\n}\n\n// contracts/libs/memory/Message.sol\n\n/// Message is a memory over over a formatted message payload.\ntype Message is uint256;\n\nusing MessageLib for Message global;\n\n/// Library for formatting the various messages supported by Origin and Destination.\n///\n/// # Message memory layout\n///\n/// | Position   | Field  | Type    | Bytes | Description                                             |\n/// | ---------- | ------ | ------- | ----- | ------------------------------------------------------- |\n/// | [000..017) | header | uint136 | 17    | Encoded general routing information for the message     |\n/// | [017..AAA) | body   | bytes   | ??    | Formatted payload (according to flag) with message body |\nlibrary MessageLib {\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MemViewLib for bytes;\n    using HeaderLib for MemView;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_HEADER = 0;\n    uint256 private constant OFFSET_BODY = OFFSET_HEADER + HEADER_LENGTH;\n\n    // ══════════════════════════════════════════════════ MESSAGE ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns formatted message with provided fields.\n     * @param header_   Encoded general routing information for the message\n     * @param body_     Formatted payload (according to flag) with message body\n     * @return Formatted message\n     */\n    function formatMessage(Header header_, bytes memory body_) internal pure returns (bytes memory) {\n        return abi.encodePacked(header_, body_);\n    }\n\n    /**\n     * @notice Returns a Message view over for the given payload.\n     * @dev Will revert if the payload is not a message payload.\n     */\n    function castToMessage(bytes memory payload) internal pure returns (Message) {\n        return castToMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Message view.\n     * @dev Will revert if the memory view is not over a message payload.\n     */\n    function castToMessage(MemView memView) internal pure returns (Message) {\n        if (!isMessage(memView)) revert UnformattedMessage();\n        return Message.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Message.\n     */\n    function isMessage(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Check if headers exist in the payload\n        if (length \u003c OFFSET_BODY) return false;\n        // Check that Header is valid\n        uint256 paddedHeader = _header(memView);\n        if (!HeaderLib.isHeader(paddedHeader)) return false;\n        // Check that body is formatted according to the flag\n        // Only Base/Manager message flags exist\n        if (HeaderLib.wrapPadded(paddedHeader).flag() == MessageFlag.Base) {\n            // Check if body is a formatted base message\n            return _body(memView).isBaseMessage();\n        } else {\n            // Check if body is a formatted calldata for AgentManager call\n            return _body(memView).isCallData();\n        }\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Message message) internal pure returns (MemView) {\n        return MemView.wrap(Message.unwrap(message));\n    }\n\n    /// @notice Returns message's hash: a leaf to be inserted in the Merkle tree.\n    function leaf(Message message) internal pure returns (bytes32) {\n        // We hash header and body separately to make message proofs easier to verify\n        Header header_ = message.header();\n        // Only Base/Manager message flags exist\n        if (header_.flag() == MessageFlag.Base) {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToBaseMessage().leaf());\n        } else {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToCallData().leaf());\n        }\n    }\n\n    // ══════════════════════════════════════════════ MESSAGE SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns message's encoded header field.\n    function header(Message message) internal pure returns (Header) {\n        return HeaderLib.wrapPadded((message.unwrap().indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH})));\n    }\n\n    /// @notice Returns message's body field as an untyped memory view.\n    function body(Message message) internal pure returns (MemView) {\n        MemView memView = message.unwrap();\n        return _body(memView);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns message's padded header without checking that it is a valid header.\n    function _header(MemView memView) private pure returns (uint256) {\n        return memView.indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH});\n    }\n\n    /// @dev Returns an untyped memory view over the body field without checking\n    /// if the whole payload or the body are properly formatted.\n    function _body(MemView memView) private pure returns (MemView) {\n        return memView.sliceFrom({index_: OFFSET_BODY});\n    }\n}\n\n// contracts/base/AgentSecured.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for messaging contracts that are secured by the agent manager.\n * `AgentSecured` relies on `AgentManager` to provide the following functionality:\n * - Keep track of agents and their statuses.\n * - Pass agent-signed statements that were verified by the agent manager.\n * - These statements are considered valid indefinitely, unless the agent is disputed.\n * - Disputes are opened and resolved by the agent manager.\n * \u003e `AgentSecured` implementation should never use statements signed by agents that are disputed.\n */\nabstract contract AgentSecured is MessagingBase, IAgentSecured {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    address public immutable agentManager;\n\n    /// @inheritdoc IAgentSecured\n    address public immutable inbox;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    // (agent index =\u003e their dispute status: flag, openedAt, resolvedAt)\n    mapping(uint32 =\u003e DisputeStatus) internal _disputes;\n\n    /// @dev gap for upgrade safety\n    uint256[49] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    modifier onlyAgentManager() {\n        if (msg.sender != agentManager) revert CallerNotAgentManager();\n        _;\n    }\n\n    modifier onlyInbox() {\n        if (msg.sender != inbox) revert CallerNotInbox();\n        _;\n    }\n\n    constructor(string memory version_, uint32 synapseDomain_, address agentManager_, address inbox_)\n        MessagingBase(version_, synapseDomain_)\n    {\n        agentManager = agentManager_;\n        inbox = inbox_;\n    }\n\n    // ════════════════════════════════════════════ ONLY AGENT MANAGER ═════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external onlyAgentManager {\n        uint40 openedAt = ChainContext.blockTimestamp();\n        DisputeStatus memory status = DisputeStatus({flag: DisputeFlag.Pending, openedAt: openedAt, resolvedAt: 0});\n        _disputes[guardIndex] = status;\n        _disputes[notaryIndex] = status;\n    }\n\n    /// @inheritdoc IAgentSecured\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external onlyAgentManager {\n        // Update the dispute status of the slashed agent first.\n        uint40 resolvedAt = ChainContext.blockTimestamp();\n        _disputes[slashedIndex].flag = DisputeFlag.Slashed;\n        _disputes[slashedIndex].resolvedAt = resolvedAt;\n        // Mark the rival agent as not disputed, if there was an ongoing dispute.\n        if (rivalIndex != 0) {\n            _disputes[rivalIndex].flag = DisputeFlag.None;\n            _disputes[rivalIndex].resolvedAt = resolvedAt;\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function agentStatus(address agent) external view returns (AgentStatus memory) {\n        return _agentStatus(agent);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status) {\n        return _getAgent(index);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory) {\n        return _disputes[agentIndex];\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns status of the given agent: (flag, domain, index).\n    function _agentStatus(address agent) internal view returns (AgentStatus memory) {\n        return IAgentManager(agentManager).agentStatus(agent);\n    }\n\n    /// @dev Returns agent and their status for a given agent index. Returns zero values for non existing indexes.\n    function _getAgent(uint256 index) internal view returns (address agent, AgentStatus memory status) {\n        return IAgentManager(agentManager).getAgent(index);\n    }\n\n    /// @dev Checks if a Dispute exists for the given Notary. This function returns true, if\n    /// Notary is in ongoing Dispute, or if Dispute was resolved not in Notary's favor.\n    /// In both cases we can't trust Notary's data.\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeExists(uint32 notaryIndex) internal view returns (bool) {\n        return _disputes[notaryIndex].flag != DisputeFlag.None;\n    }\n\n    /// @dev Checks if a Notary recently won a Dispute and is still in the \"post-dispute\" timeout period.\n    /// In this period we still can't trust Notary's data, though we can optimistically assume that\n    /// that the data will be correct after the timeout (assuming no new Disputes are opened).\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeTimeout(uint32 notaryIndex) internal view returns (bool) {\n        DisputeStatus memory status = _disputes[notaryIndex];\n        // Exit early if Notary is in ongoing Dispute / slashed.\n        if (status.flag != DisputeFlag.None) return false;\n        // Check if Notary has been in any Dispute at all.\n        if (status.openedAt == 0) return false;\n        // Otherwise check if the Dispute timeout is still active.\n        return block.timestamp \u003c status.resolvedAt + DISPUTE_TIMEOUT_NOTARY;\n    }\n}\n\n// contracts/hubs/StateHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StateHub` is a parent contract for `Origin`. It is responsible for the following:\n/// - Keeping track of the historical Origin Merkle Tree containing all the message hashes.\n/// - Keeping track of the historical Origin States, as well as verifying their validity.\nabstract contract StateHub is AgentSecured, StateHubEvents, IStateHub {\n    using SafeCast for uint256;\n    using StateLib for bytes;\n\n    struct OriginState {\n        uint40 blockNumber;\n        uint40 timestamp;\n        GasData gasData;\n    }\n    // Bits left for tight packing: 80\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Historical Merkle Tree\n    /// Note: Takes two storage slots\n    HistoricalTree private _tree;\n\n    /// @dev All historical contract States\n    OriginState[] private _originStates;\n\n    /// @dev gap for upgrade safety\n    uint256[47] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IStateHub\n    function isValidState(bytes memory statePayload) external view returns (bool isValid) {\n        // This will revert if payload is not a formatted state\n        State state = statePayload.castToState();\n        return _isValidState(state);\n    }\n\n    /// @inheritdoc IStateHub\n    function statesAmount() external view returns (uint256) {\n        return _originStates.length;\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestLatestState() external view returns (bytes memory stateData) {\n        // This never underflows, assuming the contract was initialized\n        return suggestState(_nextNonce() - 1);\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestState(uint32 nonce) public view returns (bytes memory stateData) {\n        // This will revert if nonce is out of range\n        bytes32 root = _tree.root(nonce);\n        return _formatOriginState(_originStates[nonce], root, localDomain, nonce);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Initializes the saved states list by inserting a state for an empty Merkle Tree.\n    function _initializeStates() internal {\n        // This should only be called once, when the contract is initialized\n        // This will revert if _tree.roots is non-empty\n        bytes32 savedRoot = _tree.initializeRoots();\n        // Save root for empty merkle _tree with block number and timestamp of initialization\n        _saveState(savedRoot, _toOriginState());\n    }\n\n    /// @dev Inserts leaf into the Merkle Tree and saves the updated origin State.\n    function _insertAndSave(bytes32 leaf) internal {\n        bytes32 newRoot = _tree.insert(leaf);\n        _saveState(newRoot, _toOriginState());\n    }\n\n    /// @dev Saves an updated state of the Origin contract\n    function _saveState(bytes32 root, OriginState memory state) internal {\n        uint32 nonce = _nextNonce();\n        _originStates.push(state);\n        // Emit event with raw state data\n        emit StateSaved(_formatOriginState(state, root, localDomain, nonce));\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns nonce of the next sent message: the amount of saved States so far.\n    /// This always equals to \"total amount of sent messages\" plus 1.\n    function _nextNonce() internal view returns (uint32) {\n        // TODO: consider using more than 32 bits for origin nonces\n        return _originStates.length.toUint32();\n    }\n\n    /// @dev Checks if a state is valid, i.e. if it matches the historical one.\n    /// Reverts, if state refers to another Origin contract.\n    function _isValidState(State state) internal view returns (bool) {\n        // Check if state refers to this contract\n        if (state.origin() != localDomain) revert IncorrectOriginDomain();\n        // Check if nonce exists\n        uint32 nonce = state.nonce();\n        if (nonce \u003e= _originStates.length) return false;\n        // Check if state root matches the historical one\n        if (state.root() != _tree.root(nonce)) return false;\n        // Check if state metadata matches the historical one\n        return _areEqual(state, _originStates[nonce]);\n    }\n\n    // ═════════════════════════════════════════════ STRUCT FORMATTING ═════════════════════════════════════════════════\n\n    /// @dev Returns a formatted payload for a stored OriginState.\n    function _formatOriginState(OriginState memory originState, bytes32 root, uint32 origin, uint32 nonce)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return StateLib.formatState({\n            root_: root,\n            origin_: origin,\n            nonce_: nonce,\n            blockNumber_: originState.blockNumber,\n            timestamp_: originState.timestamp,\n            gasData_: originState.gasData\n        });\n    }\n\n    /// @dev Child contract should implement the logic for getting the current gas data from the gas oracle\n    /// to be saved as part of the Origin State.\n    // solhint-disable-next-line ordering\n    function _fetchGasData() internal view virtual returns (GasData);\n\n    /// @dev Returns a OriginState struct to save in the contract.\n    function _toOriginState() internal view returns (OriginState memory originState) {\n        originState.blockNumber = ChainContext.blockNumber();\n        originState.timestamp = ChainContext.blockTimestamp();\n        originState.gasData = _fetchGasData();\n    }\n\n    /// @dev Checks that a state and its Origin representation are equal.\n    function _areEqual(State state, OriginState memory originState) internal pure returns (bool) {\n        return state.blockNumber() == originState.blockNumber \u0026\u0026 state.timestamp() == originState.timestamp;\n    }\n}\n\n// contracts/Origin.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Origin` contract is used for sending messages to remote chains. It is done\n/// by inserting the message hashes into the Origin Merkle, which makes it possible to\n/// prove that message was sent using the Merkle proof against the Origin Merkle Root. This essentially\n/// compresses the list of messages into a single 32-byte value that needs to be stored on the destination chain.\n/// `Origin` is responsible for the following:\n/// - Formatting the sent message payloads, and inserting their hashes into the Origin Merkle Tree.\n/// - Keeping track of its own historical states (see parent contract `StateHub`).\n/// - Enforcing minimum tip values for sent base messages based on the provided execution requests.\n/// - Distributing the collected tips upon request from a local `AgentManager` contract.\ncontract Origin is StateHub, OriginEvents, InterfaceOrigin {\n    using MemViewLib for bytes;\n    using MessageLib for bytes;\n    using TipsLib for bytes;\n    using TypeCasts for address;\n\n    address public immutable gasOracle;\n\n    modifier onlyRemoteDestination(uint32 destination) {\n        if (destination == localDomain) revert IncorrectDestinationDomain();\n        _;\n    }\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_, address gasOracle_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {\n        gasOracle = gasOracle_;\n    }\n\n    /// @notice Initializes Origin contract:\n    /// - msg.sender is set as contract owner\n    /// - State of \"empty merkle tree\" is saved\n    function initialize() external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize \"states\": state of an \"empty merkle tree\" is saved\n        _initializeStates();\n    }\n\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable onlyRemoteDestination(destination) returns (uint32 messageNonce, bytes32 messageHash) {\n        // Check that content is not too large\n        if (content.length \u003e MAX_CONTENT_BYTES) revert ContentLengthTooBig();\n        // This will revert if msg.value is lower than value of minimum tips\n        Tips tips = _getMinimumTips(destination, paddedRequest, content.length).matchValue(msg.value);\n        Request request = RequestLib.wrapPadded(paddedRequest);\n        // Format the BaseMessage body\n        bytes memory body = BaseMessageLib.formatBaseMessage({\n            sender_: msg.sender.addressToBytes32(),\n            recipient_: recipient,\n            tips_: tips,\n            request_: request,\n            content_: content\n        });\n        // Send the message\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Base, body);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        onlyAgentManager\n        onlyRemoteDestination(destination)\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // AgentManager (checked via modifier) is responsible for constructing the calldata payload correctly.\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Manager, payload);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function withdrawTips(address recipient, uint256 amount) external onlyAgentManager {\n        if (address(this).balance \u003c amount) revert InsufficientEthBalance();\n        (bool success,) = recipient.call{value: amount}(\"\");\n        if (!success) revert EthTransferFailed();\n        emit TipWithdrawalCompleted(recipient, amount);\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue)\n    {\n        return _getMinimumTips(destination, paddedRequest, contentLength).value();\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Sends the given message to the specified destination. Message hash is inserted\n    /// into the Origin Merkle Tree, which will enable message execution on destination chain.\n    function _sendMessage(uint32 destination, uint32 optimisticPeriod, MessageFlag flag, bytes memory body)\n        internal\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // Format the message header\n        messageNonce = _nextNonce();\n        Header header = flag.encodeHeader({\n            origin_: localDomain,\n            nonce_: messageNonce,\n            destination_: destination,\n            optimisticPeriod_: optimisticPeriod\n        });\n        // Format the full message payload\n        bytes memory msgPayload = MessageLib.formatMessage(header, body);\n        // Insert new leaf into the Origin Merkle Tree and save the updated state\n        messageHash = msgPayload.castToMessage().leaf();\n        _insertAndSave(messageHash);\n        // Emit event with message information\n        emit Sent(messageHash, messageNonce, destination, msgPayload);\n        // Update the gas oracle data. We do this after the provided tips are checked so that\n        // the provided message is sent in the event that the gas oracle data is updated to a higher value.\n        InterfaceGasOracle(gasOracle).updateGasData(destination);\n        // TODO: consider doing this before the message is sent, while adjusting GasOracle.getMinimumTips() to\n        // use the pending gas oracle data.\n    }\n\n    /// @dev Returns the minimum tips for sending a message to the given destination with the given request and content.\n    function _getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        internal\n        view\n        returns (Tips)\n    {\n        return\n            TipsLib.wrapPadded(InterfaceGasOracle(gasOracle).getMinimumTips(destination, paddedRequest, contentLength));\n    }\n\n    /// @dev Gets the current gas data from the gas oracle to be saved as part of the Origin State.\n    function _fetchGasData() internal view override returns (GasData) {\n        return GasDataLib.wrapGasData(InterfaceGasOracle(gasOracle).getGasData());\n    }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[{"components":[{"internalType":"bool","name":"allowFailure","type":"bool"},{"internalType":"bytes","name":"callData","type":"bytes"}],"internalType":"struct MultiCallable.Call[]","name":"calls","type":"tuple[]"}],"name":"multicall","outputs":[{"components":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"bytes","name":"returnData","type":"bytes"}],"internalType":"struct MultiCallable.Result[]","name":"callResults","type":"tuple[]"}],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{"multicall((bool,bytes)[])":{"notice":"Aggregates a few calls to this contract into one multicall without modifying `msg.sender`."}},"notice":"Collection of Multicall utilities. Fork of Multicall3: https://github.com/mds1/multicall/blob/master/src/Multicall3.sol","version":1},"developerDoc":{"kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"allowFailure\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"struct MultiCallable.Call[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"multicall\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"struct MultiCallable.Result[]\",\"name\":\"callResults\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"multicall((bool,bytes)[])\":{\"notice\":\"Aggregates a few calls to this contract into one multicall without modifying `msg.sender`.\"}},\"notice\":\"Collection of Multicall utilities. Fork of Multicall3: https://github.com/mds1/multicall/blob/master/src/Multicall3.sol\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Origin.sol\":\"MultiCallable\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Origin.sol\":{\"keccak256\":\"0x96775924f147f3d1f8df8cdf56731fe52a15af8d8e12e608efb8158c112b18cd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e642a27f5fab3c62b4c02e9754e9e42b1cf2e5381dbea9d3d106d23b7772ebe6\",\"dweb:/ipfs/QmUwn7ZyBvPkjnMuK8ZMSexBUdNQnVtxwyoAyT4DXLQjra\"]}},\"version\":1}"},"hashes":{"multicall((bool,bytes)[])":"60fc8466"}},"solidity/Origin.sol:NumberLib":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212209b85821ff9971639696712add805a85f9526cea4e89a1e0d72989f50fe0bdd5964736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212209b85821ff9971639696712add805a85f9526cea4e89a1e0d72989f50fe0bdd5964736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/OriginEvents.sol\n\n/// @notice A collection of events emitted by the Origin contract\nabstract contract OriginEvents {\n    /**\n     * @notice Emitted when a new message is sent.\n     * @param messageHash   Hash of message; the leaf inserted to the Merkle tree for the message\n     * @param nonce         Nonce of sent message (starts from 1)\n     * @param destination   Destination domain\n     * @param message       Raw bytes of message\n     */\n    event Sent(bytes32 indexed messageHash, uint32 indexed nonce, uint32 indexed destination, bytes message);\n\n    /**\n     * @notice Emitted when a tip withdrawal is completed.\n     * @param actor     Actor address\n     * @param tip       Tip value, denominated in local domain's wei\n     */\n    event TipWithdrawalCompleted(address actor, uint256 tip);\n}\n\n// contracts/events/StateHubEvents.sol\n\n/// @notice A collection of events emitted by the StateHub contract\nabstract contract StateHubEvents {\n    /**\n     * @notice Emitted when a new Origin State is saved after a message was sent.\n     * @param state     Raw payload with state data\n     */\n    event StateSaved(bytes state);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n    /**\n     * @notice Check that a given state is valid: matches the historical state of Origin contract.\n     * Note: any Agent including an invalid state in their snapshot will be slashed\n     * upon providing the snapshot and agent signature for it to Origin contract.\n     * @dev Will revert if any of these is true:\n     *  - State payload is not properly formatted.\n     * @param statePayload      Raw payload with state data\n     * @return isValid          Whether the provided state is valid\n     */\n    function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns the amount of saved states so far.\n     * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n     */\n    function statesAmount() external view returns (uint256);\n\n    /**\n     * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @return statePayload     Raw payload with the latest state data\n     */\n    function suggestLatestState() external view returns (bytes memory statePayload);\n\n    /**\n     * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @param nonce             Historical nonce to form a state\n     * @return statePayload     Raw payload with historical state data\n     */\n    function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/InterfaceGasOracle.sol\n\ninterface InterfaceGasOracle {\n    /**\n     * @notice Fetches the latest gas data for the chain from `Destination` contract,\n     * and uses it to update the oracle values for the requested chain.\n     * @param domain    Domain to update the gas data for\n     */\n    function updateGasData(uint32 domain) external;\n\n    /**\n     * @notice Returns the gas data for the local chain.\n     */\n    function getGasData() external view returns (uint256 paddedGasData);\n\n    /**\n     * @notice Returns the gas data for the given domain, in the decoded format.\n     * @param domain        Domain of chain to get gas data for\n     * @return gasPrice     Gas price for the chain (in Wei per gas unit)\n     * @return dataPrice    Calldata price (in Wei per byte of content)\n     * @return execBuffer   Tx fee safety buffer for message execution (in Wei)\n     * @return amortAttCost Amortized cost for attestation submission (in Wei)\n     * @return etherPrice   Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n     * @return markup       Markup for the message execution (in BWAD)\n     */\n    function getDecodedGasData(uint32 domain)\n        external\n        view\n        returns (\n            uint256 gasPrice,\n            uint256 dataPrice,\n            uint256 execBuffer,\n            uint256 amortAttCost,\n            uint256 etherPrice,\n            uint256 markup\n        );\n\n    /**\n     * @notice Returns the minimum tips for sending a message to a given destination.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return paddedTips       Padded encoded minimum tips information\n     */\n    function getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 paddedTips);\n}\n\n// contracts/interfaces/InterfaceOrigin.sol\n\ninterface InterfaceOrigin {\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /**\n     * @notice Send a message to the recipient located on destination domain.\n     * @dev Recipient has to conform to IMessageRecipient interface, otherwise message won't be delivered.\n     * Will revert if any of these is true:\n     * - `destination` is equal to contract's local domain\n     * - `content` length is greater than `MAX_CONTENT_BYTES`\n     * - `msg.value` is lower than value of minimum tips for the given message\n     * @param destination           Domain of destination chain\n     * @param recipient             Address of recipient on destination chain as bytes32\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param paddedRequest         Padded encoded message execution request on destination chain\n     * @param content               Raw bytes content of message\n     * @return messageNonce         Nonce of the sent message\n     * @return messageHash          Hash of the sent message\n     */\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable returns (uint32 messageNonce, bytes32 messageHash);\n\n    /**\n     * @notice Send a manager message to the destination domain.\n     * @dev This could only be called by AgentManager, which takes care of encoding the calldata payload.\n     * Note: (msgOrigin, proofMaturity) security args will be added to payload on the destination chain\n     * so that the AgentManager could verify where the Manager Message came from and how mature is the proof.\n     * Note: function is not payable, as no tips are required for sending a manager message.\n     * Will revert if `destination` is equal to contract's local domain.\n     * @param destination           Domain of destination chain\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param payload               Payload for calling AgentManager on destination chain (with extra security args)\n     */\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        returns (uint32 messageNonce, bytes32 messageHash);\n\n    // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Withdraws locked base message tips to the recipient.\n     * @dev Could only be called by a local AgentManager.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function withdrawTips(address recipient, uint256 amount) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the minimum tips value for sending a message to a given destination.\n     * @dev Using at least `tipsValue` as `msg.value` for `sendBaseMessage()`\n     * will guarantee that the message will be accepted.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return tipsValue        Minimum tips value for a message to be accepted\n     */\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue);\n}\n\n// contracts/libs/Constants.sol\n\n// Here we define common constants to enable their easier reusing later.\n\n// ══════════════════════════════════ MERKLE ═══════════════════════════════════\n/// @dev Height of the Agent Merkle Tree\nuint256 constant AGENT_TREE_HEIGHT = 32;\n/// @dev Height of the Origin Merkle Tree\nuint256 constant ORIGIN_TREE_HEIGHT = 32;\n/// @dev Height of the Snapshot Merkle Tree. Allows up to 64 leafs, e.g. up to 32 states\nuint256 constant SNAPSHOT_TREE_HEIGHT = 6;\n// ══════════════════════════════════ STRUCTS ══════════════════════════════════\n/// @dev See Attestation.sol: (bytes32,bytes32,uint32,uint40,uint40): 32+32+4+5+5\nuint256 constant ATTESTATION_LENGTH = 78;\n/// @dev See GasData.sol: (uint16,uint16,uint16,uint16,uint16,uint16): 2+2+2+2+2+2\nuint256 constant GAS_DATA_LENGTH = 12;\n/// @dev See Receipt.sol: (uint32,uint32,bytes32,bytes32,uint8,address,address,address): 4+4+32+32+1+20+20+20\nuint256 constant RECEIPT_LENGTH = 133;\n/// @dev See State.sol: (bytes32,uint32,uint32,uint40,uint40,GasData): 32+4+4+5+5+len(GasData)\nuint256 constant STATE_LENGTH = 50 + GAS_DATA_LENGTH;\n/// @dev Maximum amount of states in a single snapshot. Each state produces two leafs in the tree\nuint256 constant SNAPSHOT_MAX_STATES = 1 \u003c\u003c (SNAPSHOT_TREE_HEIGHT - 1);\n// ══════════════════════════════════ MESSAGE ══════════════════════════════════\n/// @dev See Header.sol: (uint8,uint32,uint32,uint32,uint32): 1+4+4+4+4\nuint256 constant HEADER_LENGTH = 17;\n/// @dev See Request.sol: (uint96,uint64,uint32): 12+8+4\nuint256 constant REQUEST_LENGTH = 24;\n/// @dev See Tips.sol: (uint64,uint64,uint64,uint64): 8+8+8+8\nuint256 constant TIPS_LENGTH = 32;\n/// @dev The amount of discarded last bits when encoding tip values\nuint256 constant TIPS_GRANULARITY = 32;\n/// @dev Tip values could be only the multiples of TIPS_MULTIPLIER\nuint256 constant TIPS_MULTIPLIER = 1 \u003c\u003c TIPS_GRANULARITY;\n// ══════════════════════════════ STATEMENT SALTS ══════════════════════════════\n/// @dev Salts for signing various statements\nbytes32 constant ATTESTATION_VALID_SALT = keccak256(\"ATTESTATION_VALID_SALT\");\nbytes32 constant ATTESTATION_INVALID_SALT = keccak256(\"ATTESTATION_INVALID_SALT\");\nbytes32 constant RECEIPT_VALID_SALT = keccak256(\"RECEIPT_VALID_SALT\");\nbytes32 constant RECEIPT_INVALID_SALT = keccak256(\"RECEIPT_INVALID_SALT\");\nbytes32 constant SNAPSHOT_VALID_SALT = keccak256(\"SNAPSHOT_VALID_SALT\");\nbytes32 constant STATE_INVALID_SALT = keccak256(\"STATE_INVALID_SALT\");\n// ═════════════════════════════════ PROTOCOL ══════════════════════════════════\n/// @dev Optimistic period for new agent roots in LightManager\nuint32 constant AGENT_ROOT_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Timeout between the agent root could be proposed and resolved in LightManager\nuint32 constant AGENT_ROOT_PROPOSAL_TIMEOUT = 12 hours;\nuint32 constant BONDING_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Amount of time that the Notary will not be considered active after they won a dispute\nuint32 constant DISPUTE_TIMEOUT_NOTARY = 12 hours;\n/// @dev Amount of time without fresh data from Notaries before contract owner can resolve stuck disputes manually\nuint256 constant FRESH_DATA_TIMEOUT = 4 hours;\n/// @dev Maximum bytes per message = 2 KiB (somewhat arbitrarily set to begin)\nuint256 constant MAX_CONTENT_BYTES = 2 * 2 ** 10;\n/// @dev Maximum value for the summit tip that could be set in GasOracle\nuint256 constant MAX_SUMMIT_TIP = 0.01 ether;\n\n// contracts/libs/Errors.sol\n\n// ══════════════════════════════ INVALID CALLER ═══════════════════════════════\n\nerror CallerNotAgentManager();\nerror CallerNotDestination();\nerror CallerNotInbox();\nerror CallerNotSummit();\n\n// ══════════════════════════════ INCORRECT DATA ═══════════════════════════════\n\nerror IncorrectAttestation();\nerror IncorrectAgentDomain();\nerror IncorrectAgentIndex();\nerror IncorrectAgentProof();\nerror IncorrectAgentRoot();\nerror IncorrectDataHash();\nerror IncorrectDestinationDomain();\nerror IncorrectOriginDomain();\nerror IncorrectSnapshotProof();\nerror IncorrectSnapshotRoot();\nerror IncorrectState();\nerror IncorrectStatesAmount();\nerror IncorrectTipsProof();\nerror IncorrectVersionLength();\n\nerror IncorrectNonce();\nerror IncorrectSender();\nerror IncorrectRecipient();\n\nerror FlagOutOfRange();\nerror IndexOutOfRange();\nerror NonceOutOfRange();\n\nerror OutdatedNonce();\n\nerror UnformattedAttestation();\nerror UnformattedAttestationReport();\nerror UnformattedBaseMessage();\nerror UnformattedCallData();\nerror UnformattedCallDataPrefix();\nerror UnformattedMessage();\nerror UnformattedReceipt();\nerror UnformattedReceiptReport();\nerror UnformattedSignature();\nerror UnformattedSnapshot();\nerror UnformattedState();\nerror UnformattedStateReport();\n\n// ═══════════════════════════════ MERKLE TREES ════════════════════════════════\n\nerror LeafNotProven();\nerror MerkleTreeFull();\nerror NotEnoughLeafs();\nerror TreeHeightTooLow();\n\n// ═════════════════════════════ OPTIMISTIC PERIOD ═════════════════════════════\n\nerror BaseClientOptimisticPeriod();\nerror MessageOptimisticPeriod();\nerror SlashAgentOptimisticPeriod();\nerror WithdrawTipsOptimisticPeriod();\nerror ZeroProofMaturity();\n\n// ═══════════════════════════════ AGENT MANAGER ═══════════════════════════════\n\nerror AgentNotGuard();\nerror AgentNotNotary();\n\nerror AgentCantBeAdded();\nerror AgentNotActive();\nerror AgentNotActiveNorUnstaking();\nerror AgentNotFraudulent();\nerror AgentNotUnstaking();\nerror AgentUnknown();\n\nerror AgentRootNotProposed();\nerror AgentRootTimeoutNotOver();\n\nerror NotStuck();\n\nerror DisputeAlreadyResolved();\nerror DisputeNotOpened();\nerror DisputeTimeoutNotOver();\nerror GuardInDispute();\nerror NotaryInDispute();\n\nerror MustBeSynapseDomain();\nerror SynapseDomainForbidden();\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\nerror AlreadyExecuted();\nerror AlreadyFailed();\nerror DuplicatedSnapshotRoot();\nerror IncorrectMagicValue();\nerror GasLimitTooLow();\nerror GasSuppliedTooLow();\n\n// ══════════════════════════════════ ORIGIN ═══════════════════════════════════\n\nerror ContentLengthTooBig();\nerror EthTransferFailed();\nerror InsufficientEthBalance();\n\n// ════════════════════════════════ GAS ORACLE ═════════════════════════════════\n\nerror LocalGasDataNotSet();\nerror RemoteGasDataNotSet();\n\n// ═══════════════════════════════════ TIPS ════════════════════════════════════\n\nerror SummitTipTooHigh();\nerror TipsClaimMoreThanEarned();\nerror TipsClaimZero();\nerror TipsOverflow();\nerror TipsValueTooLow();\n\n// ════════════════════════════════ MEMORY VIEW ════════════════════════════════\n\nerror IndexedTooMuch();\nerror ViewOverrun();\nerror OccupiedMemory();\nerror UnallocatedMemory();\nerror PrecompileOutOfGas();\n\n// ═════════════════════════════════ MULTICALL ═════════════════════════════════\n\nerror MulticallFailed();\n\n// contracts/libs/TypeCasts.sol\n\nlibrary TypeCasts {\n    // alignment preserving cast\n    function addressToBytes32(address addr) internal pure returns (bytes32) {\n        return bytes32(uint256(uint160(addr)));\n    }\n\n    // alignment preserving cast\n    function bytes32ToAddress(bytes32 buf) internal pure returns (address) {\n        return address(uint160(uint256(buf)));\n    }\n}\n\n// contracts/libs/stack/Number.sol\n\n/// Number is a compact representation of uint256, that is fit into 16 bits\n/// with the maximum relative error under 0.4%.\ntype Number is uint16;\n\nusing NumberLib for Number global;\n\n/// # Number\n/// Library for compact representation of uint256 numbers.\n/// - Number is stored using mantissa and exponent, each occupying 8 bits.\n/// - Numbers under 2**8 are stored as `mantissa` with `exponent = 0xFF`.\n/// - Numbers at least 2**8 are approximated as `(256 + mantissa) \u003c\u003c exponent`\n/// \u003e - `0 \u003c= mantissa \u003c 256`\n/// \u003e - `0 \u003c= exponent \u003c= 247` (`256 * 2**248` doesn't fit into uint256)\n/// # Number stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type  | Bytes |\n/// | ---------- | -------- | ----- | ----- |\n/// | (002..001] | mantissa | uint8 | 1     |\n/// | (001..000] | exponent | uint8 | 1     |\n\nlibrary NumberLib {\n    /// @dev Amount of bits to shift to mantissa field\n    uint16 private constant SHIFT_MANTISSA = 8;\n\n    /// @notice For bwad math (binary wad) we use 2**64 as \"wad\" unit.\n    /// @dev We are using not using 10**18 as wad, because it is not stored precisely in NumberLib.\n    uint256 internal constant BWAD_SHIFT = 64;\n    uint256 internal constant BWAD = 1 \u003c\u003c BWAD_SHIFT;\n    /// @notice ~0.1% in bwad units.\n    uint256 internal constant PER_MILLE_SHIFT = BWAD_SHIFT - 10;\n    uint256 internal constant PER_MILLE = 1 \u003c\u003c PER_MILLE_SHIFT;\n\n    /// @notice Compresses uint256 number into 16 bits.\n    function compress(uint256 value) internal pure returns (Number) {\n        // Find `msb` such as `2**msb \u003c= value \u003c 2**(msb + 1)`\n        uint256 msb = mostSignificantBit(value);\n        // We want to preserve 9 bits of precision.\n        // The highest bit is always 1, so we can skip it.\n        // The remaining 8 highest bits are stored as mantissa.\n        if (msb \u003c 8) {\n            // Value is less than 2**8, so we can use value as mantissa with \"-1\" exponent.\n            return _encode(uint8(value), 0xFF);\n        } else {\n            // We use `msb - 8` as exponent otherwise. Note that `exponent \u003e= 0`.\n            unchecked {\n                uint256 exponent = msb - 8;\n                // Shifting right by `msb-8` bits will shift the \"remaining 8 highest bits\" into the 8 lowest bits.\n                // uint8() will truncate the highest bit.\n                return _encode(uint8(value \u003e\u003e exponent), uint8(exponent));\n            }\n        }\n    }\n\n    /// @notice Decompresses 16 bits number into uint256.\n    /// @dev The outcome is an approximation of the original number: `(value - value / 256) \u003c number \u003c= value`.\n    function decompress(Number number) internal pure returns (uint256 value) {\n        // Isolate 8 highest bits as the mantissa.\n        uint256 mantissa = Number.unwrap(number) \u003e\u003e SHIFT_MANTISSA;\n        // This will truncate the highest bits, leaving only the exponent.\n        uint256 exponent = uint8(Number.unwrap(number));\n        if (exponent == 0xFF) {\n            return mantissa;\n        } else {\n            unchecked {\n                return (256 + mantissa) \u003c\u003c (exponent);\n            }\n        }\n    }\n\n    /// @dev Returns the most significant bit of `x`\n    /// https://solidity-by-example.org/bitwise/\n    function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\n        // To find `msb` we determine it bit by bit, starting from the highest one.\n        // `0 \u003c= msb \u003c= 255`, so we start from the highest bit, 1\u003c\u003c7 == 128.\n        // If `x` is at least 2**128, then the highest bit of `x` is at least 128.\n        // solhint-disable no-inline-assembly\n        assembly {\n            // `f` is set to 1\u003c\u003c7 if `x \u003e= 2**128` and to 0 otherwise.\n            let f := shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\n            // If `x \u003e= 2**128` then set `msb` highest bit to 1 and shift `x` right by 128.\n            // Otherwise, `msb` remains 0 and `x` remains unchanged.\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        // `x` is now at most 2**128 - 1. Continue the same way, the next highest bit is 1\u003c\u003c6 == 64.\n        assembly {\n            // `f` is set to 1\u003c\u003c6 if `x \u003e= 2**64` and to 0 otherwise.\n            let f := shl(6, gt(x, 0xFFFFFFFFFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c5 if `x \u003e= 2**32` and to 0 otherwise.\n            let f := shl(5, gt(x, 0xFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c4 if `x \u003e= 2**16` and to 0 otherwise.\n            let f := shl(4, gt(x, 0xFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c3 if `x \u003e= 2**8` and to 0 otherwise.\n            let f := shl(3, gt(x, 0xFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c2 if `x \u003e= 2**4` and to 0 otherwise.\n            let f := shl(2, gt(x, 0xF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c1 if `x \u003e= 2**2` and to 0 otherwise.\n            let f := shl(1, gt(x, 0x3))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1 if `x \u003e= 2**1` and to 0 otherwise.\n            let f := gt(x, 0x1)\n            msb := or(msb, f)\n        }\n    }\n\n    /// @dev Wraps (mantissa, exponent) pair into Number.\n    function _encode(uint8 mantissa, uint8 exponent) private pure returns (Number) {\n        // Casts below are upcasts, so they are safe.\n        return Number.wrap(uint16(mantissa) \u003c\u003c SHIFT_MANTISSA | uint16(exponent));\n    }\n}\n\n// contracts/libs/stack/Request.sol\n\n/// Request is encoded data with \"message execution request\".\ntype Request is uint192;\n\nusing RequestLib for Request global;\n\n/// Library for formatting _the request part_ of _the base messages_.\n/// - Request represents a message sender requirements for the message execution on the destination chain.\n/// - Request occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n/// \u003e gasDrop field is included for future compatibility and is ignored at the moment.\n///\n/// # Request stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type   | Bytes | Description                                          |\n/// | ---------- | -------- | ------ | ----- | ---------------------------------------------------- |\n/// | (024..012] | gasDrop  | uint96 | 12    | Minimum amount of gas token to drop to the recipient |\n/// | (012..004] | gasLimit | uint64 | 8     | Minimum amount of gas units to supply for execution  |\n/// | (004..000] | version  | uint32 | 4     | Base message version to pass to the recipient        |\n\nlibrary RequestLib {\n    /// @dev Amount of bits to shift to gasDrop field\n    uint192 private constant SHIFT_GAS_DROP = 12 * 8;\n    /// @dev Amount of bits to shift to gasLimit field\n    uint192 private constant SHIFT_GAS_LIMIT = 4 * 8;\n\n    /// @notice Returns an encoded request with the given fields\n    /// @param gasDrop_     Minimum amount of gas token to drop to the recipient (ignored at the moment)\n    /// @param gasLimit_    Minimum amount of gas units to supply for execution\n    /// @param version_     Base message version to pass to the recipient\n    function encodeRequest(uint96 gasDrop_, uint64 gasLimit_, uint32 version_) internal pure returns (Request) {\n        // Casts below are upcasts, so they are safe\n        return Request.wrap(uint192(gasDrop_) \u003c\u003c SHIFT_GAS_DROP | uint192(gasLimit_) \u003c\u003c SHIFT_GAS_LIMIT | version_);\n    }\n\n    /// @notice Wraps the padded encoded request into a Request-typed value.\n    /// @dev The \"padded\" request is simply an encoded request casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded requests\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedRequest) internal pure returns (Request) {\n        // Casting to uint192 will truncate the highest bits, which is the behavior we want\n        return Request.wrap(uint192(paddedRequest));\n    }\n\n    /// @notice Returns the requested of gas token to drop to the recipient.\n    function gasDrop(Request request) internal pure returns (uint96) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return uint96(Request.unwrap(request) \u003e\u003e SHIFT_GAS_DROP);\n    }\n\n    /// @notice Returns the requested minimum amount of gas units to supply for execution.\n    function gasLimit(Request request) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Request.unwrap(request) \u003e\u003e SHIFT_GAS_LIMIT);\n    }\n\n    /// @notice Returns the requested base message version to pass to the recipient.\n    function version(Request request) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Request.unwrap(request));\n    }\n}\n\n// node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        require(value \u003c= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        require(value \u003c= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        require(value \u003c= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value \u003c= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        require(value \u003c= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        require(value \u003c= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        require(value \u003c= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        require(value \u003c= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        require(value \u003c= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        require(value \u003c= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        require(value \u003c= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        require(value \u003c= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        require(value \u003c= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        require(value \u003c= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        require(value \u003c= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value \u003c= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        require(value \u003c= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        require(value \u003c= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        require(value \u003c= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value \u003c= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        require(value \u003c= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        require(value \u003c= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        require(value \u003c= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value \u003c= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        require(value \u003c= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        require(value \u003c= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        require(value \u003c= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value \u003c= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        require(value \u003c= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value \u003c= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value \u003c= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     *\n     * _Available since v3.0._\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value \u003e= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     *\n     * _Available since v3.0._\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value \u003c= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     *\n     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length \u003e 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance \u003e= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance \u003e= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length \u003e 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n\n// contracts/base/MultiCallable.sol\n\n/// @notice Collection of Multicall utilities. Fork of Multicall3:\n/// https://github.com/mds1/multicall/blob/master/src/Multicall3.sol\nabstract contract MultiCallable {\n    struct Call {\n        bool allowFailure;\n        bytes callData;\n    }\n\n    struct Result {\n        bool success;\n        bytes returnData;\n    }\n\n    /// @notice Aggregates a few calls to this contract into one multicall without modifying `msg.sender`.\n    function multicall(Call[] calldata calls) external returns (Result[] memory callResults) {\n        uint256 amount = calls.length;\n        callResults = new Result[](amount);\n        Call calldata call_;\n        for (uint256 i = 0; i \u003c amount;) {\n            call_ = calls[i];\n            Result memory result = callResults[i];\n            // We perform a delegate call to ourselves here. Delegate call does not modify `msg.sender`, so\n            // this will have the same effect as if `msg.sender` performed all the calls themselves one by one.\n            // solhint-disable-next-line avoid-low-level-calls\n            (result.success, result.returnData) = address(this).delegatecall(call_.callData);\n            // solhint-disable-next-line no-inline-assembly\n            assembly {\n                // Revert if the call fails and failure is not allowed\n                // `allowFailure := calldataload(call_)` and `success := mload(result)`\n                if iszero(or(calldataload(call_), mload(result))) {\n                    // Revert with `0x4d6a2328` (function selector for `MulticallFailed()`)\n                    mstore(0x00, 0x4d6a232800000000000000000000000000000000000000000000000000000000)\n                    revert(0x00, 0x04)\n                }\n            }\n            unchecked {\n                ++i;\n            }\n        }\n    }\n}\n\n// contracts/base/Version.sol\n\n/**\n * @title Versioned\n * @notice Version getter for contracts. Doesn't use any storage slots, meaning\n * it will never cause any troubles with the upgradeable contracts. For instance, this contract\n * can be added or removed from the inheritance chain without shifting the storage layout.\n */\nabstract contract Versioned {\n    /**\n     * @notice Struct that is mimicking the storage layout of a string with 32 bytes or less.\n     * Length is limited by 32, so the whole string payload takes two memory words:\n     * @param length    String length\n     * @param data      String characters\n     */\n    struct _ShortString {\n        uint256 length;\n        bytes32 data;\n    }\n\n    /// @dev Length of the \"version string\"\n    uint256 private immutable _length;\n    /// @dev Bytes representation of the \"version string\".\n    /// Strings with length over 32 are not supported!\n    bytes32 private immutable _data;\n\n    constructor(string memory version_) {\n        _length = bytes(version_).length;\n        if (_length \u003e 32) revert IncorrectVersionLength();\n        // bytes32 is left-aligned =\u003e this will store the byte representation of the string\n        // with the trailing zeroes to complete the 32-byte word\n        _data = bytes32(bytes(version_));\n    }\n\n    function version() external view returns (string memory versionString) {\n        // Load the immutable values to form the version string\n        _ShortString memory str = _ShortString(_length, _data);\n        // The only way to do this cast is doing some dirty assembly\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            versionString := str\n        }\n    }\n}\n\n// contracts/libs/ChainContext.sol\n\n/// @notice Library for accessing chain context variables as tightly packed integers.\n/// Messaging contracts should rely on this library for accessing chain context variables\n/// instead of doing the casting themselves.\nlibrary ChainContext {\n    using SafeCast for uint256;\n\n    /// @notice Returns the current block number as uint40.\n    /// @dev Reverts if block number is greater than 40 bits, which is not supposed to happen\n    /// until the block.timestamp overflows (assuming block time is at least 1 second).\n    function blockNumber() internal view returns (uint40) {\n        return block.number.toUint40();\n    }\n\n    /// @notice Returns the current block timestamp as uint40.\n    /// @dev Reverts if block timestamp is greater than 40 bits, which is\n    /// supposed to happen approximately in year 36835.\n    function blockTimestamp() internal view returns (uint40) {\n        return block.timestamp.toUint40();\n    }\n\n    /// @notice Returns the chain id as uint32.\n    /// @dev Reverts if chain id is greater than 32 bits, which is not\n    /// supposed to happen in production.\n    function chainId() internal view returns (uint32) {\n        return block.chainid.toUint32();\n    }\n}\n\n// contracts/libs/Structures.sol\n\n// Here we define common enums and structures to enable their easier reusing later.\n\n// ═══════════════════════════════ AGENT STATUS ════════════════════════════════\n\n/// @dev Potential statuses for the off-chain bonded agent:\n/// - Unknown: never provided a bond =\u003e signature not valid\n/// - Active: has a bond in BondingManager =\u003e signature valid\n/// - Unstaking: has a bond in BondingManager, initiated the unstaking =\u003e signature not valid\n/// - Resting: used to have a bond in BondingManager, successfully unstaked =\u003e signature not valid\n/// - Fraudulent: proven to commit fraud, value in Merkle Tree not updated =\u003e signature not valid\n/// - Slashed: proven to commit fraud, value in Merkle Tree was updated =\u003e signature not valid\n/// Unstaked agent could later be added back to THE SAME domain by staking a bond again.\n/// Honest agent: Unknown -\u003e Active -\u003e unstaking -\u003e Resting -\u003e Active ...\n/// Malicious agent: Unknown -\u003e Active -\u003e Fraudulent -\u003e Slashed\n/// Malicious agent: Unknown -\u003e Active -\u003e Unstaking -\u003e Fraudulent -\u003e Slashed\nenum AgentFlag {\n    Unknown,\n    Active,\n    Unstaking,\n    Resting,\n    Fraudulent,\n    Slashed\n}\n\n/// @notice Struct for storing an agent in the BondingManager contract.\nstruct AgentStatus {\n    AgentFlag flag;\n    uint32 domain;\n    uint32 index;\n}\n// 184 bits available for tight packing\n\nusing StructureUtils for AgentStatus global;\n\n/// @notice Potential statuses of an agent in terms of being in dispute\n/// - None: agent is not in dispute\n/// - Pending: agent is in unresolved dispute\n/// - Slashed: agent was in dispute that lead to agent being slashed\n/// Note: agent who won the dispute has their status reset to None\nenum DisputeFlag {\n    None,\n    Pending,\n    Slashed\n}\n\n/// @notice Struct for storing dispute status of an agent.\n/// @param flag         Dispute flag: None/Pending/Slashed.\n/// @param openedAt     Timestamp when the latest agent dispute was opened (zero if not opened).\n/// @param resolvedAt   Timestamp when the latest agent dispute was resolved (zero if not resolved).\nstruct DisputeStatus {\n    DisputeFlag flag;\n    uint40 openedAt;\n    uint40 resolvedAt;\n}\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\n/// @notice Struct representing the status of Destination contract.\n/// @param snapRootTime     Timestamp when latest snapshot root was accepted\n/// @param agentRootTime    Timestamp when latest agent root was accepted\n/// @param notaryIndex      Index of Notary who signed the latest agent root\nstruct DestinationStatus {\n    uint40 snapRootTime;\n    uint40 agentRootTime;\n    uint32 notaryIndex;\n}\n\n// ═══════════════════════════════ EXECUTION HUB ═══════════════════════════════\n\n/// @notice Potential statuses of the message in Execution Hub.\n/// - None: there hasn't been a valid attempt to execute the message yet\n/// - Failed: there was a valid attempt to execute the message, but recipient reverted\n/// - Success: there was a valid attempt to execute the message, and recipient did not revert\n/// Note: message can be executed until its status is Success\nenum MessageStatus {\n    None,\n    Failed,\n    Success\n}\n\nlibrary StructureUtils {\n    /// @notice Checks that Agent is Active\n    function verifyActive(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active) {\n            revert AgentNotActive();\n        }\n    }\n\n    /// @notice Checks that Agent is Unstaking\n    function verifyUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Unstaking) {\n            revert AgentNotUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Active or Unstaking\n    function verifyActiveUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active \u0026\u0026 status.flag != AgentFlag.Unstaking) {\n            revert AgentNotActiveNorUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Fraudulent\n    function verifyFraudulent(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Fraudulent) {\n            revert AgentNotFraudulent();\n        }\n    }\n\n    /// @notice Checks that Agent is not Unknown\n    function verifyKnown(AgentStatus memory status) internal pure {\n        if (status.flag == AgentFlag.Unknown) {\n            revert AgentUnknown();\n        }\n    }\n}\n\n// contracts/libs/memory/MemView.sol\n\n/// @dev MemView is an untyped view over a portion of memory to be used instead of `bytes memory`\ntype MemView is uint256;\n\n/// @dev Attach library functions to MemView\nusing MemViewLib for MemView global;\n\n/// @notice Library for operations with the memory views.\n/// Forked from https://github.com/summa-tx/memview-sol with several breaking changes:\n/// - The codebase is ported to Solidity 0.8\n/// - Custom errors are added\n/// - The runtime type checking is replaced with compile-time check provided by User-Defined Value Types\n///   https://docs.soliditylang.org/en/latest/types.html#user-defined-value-types\n/// - uint256 is used as the underlying type for the \"memory view\" instead of bytes29.\n///   It is wrapped into MemView custom type in order not to be confused with actual integers.\n/// - Therefore the \"type\" field is discarded, allowing to allocate 16 bytes for both view location and length\n/// - The documentation is expanded\n/// - Library functions unused by the rest of the codebase are removed\n//  - Very pretty code separators are added :)\nlibrary MemViewLib {\n    /// @notice Stack layout for uint256 (from highest bits to lowest)\n    /// (32 .. 16]      loc     16 bytes    Memory address of underlying bytes\n    /// (16 .. 00]      len     16 bytes    Length of underlying bytes\n\n    // ═══════════════════════════════════════════ BUILDING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Instantiate a new untyped memory view. This should generally not be called directly.\n     * Prefer `ref` wherever possible.\n     * @param loc_          The memory address\n     * @param len_          The length\n     * @return The new view with the specified location and length\n     */\n    function build(uint256 loc_, uint256 len_) internal pure returns (MemView) {\n        uint256 end_ = loc_ + len_;\n        // Make sure that a view is not constructed that points to unallocated memory\n        // as this could be indicative of a buffer overflow attack\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            if gt(end_, mload(0x40)) { end_ := 0 }\n        }\n        if (end_ == 0) {\n            revert UnallocatedMemory();\n        }\n        return _unsafeBuildUnchecked(loc_, len_);\n    }\n\n    /**\n     * @notice Instantiate a memory view from a byte array.\n     * @dev Note that due to Solidity memory representation, it is not possible to\n     * implement a deref, as the `bytes` type stores its len in memory.\n     * @param arr           The byte array\n     * @return The memory view over the provided byte array\n     */\n    function ref(bytes memory arr) internal pure returns (MemView) {\n        uint256 len_ = arr.length;\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 loc_;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // We add 0x20, so that the view starts exactly where the array data starts\n            loc_ := add(arr, 0x20)\n        }\n        return build(loc_, len_);\n    }\n\n    // ════════════════════════════════════════════ CLONING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to the new memory.\n     * @param memView       The memory view\n     * @return arr          The cloned byte array\n     */\n    function clone(MemView memView) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        unchecked {\n            _unsafeCopyTo(memView, ptr + 0x20);\n        }\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 len_ = memView.len();\n        uint256 footprint_ = memView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    /**\n     * @notice Copies all views, joins them into a new bytearray.\n     * @param memViews      The memory views\n     * @return arr          The new byte array with joined data behind the given views\n     */\n    function join(MemView[] memory memViews) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        MemView newView;\n        unchecked {\n            newView = _unsafeJoin(memViews, ptr + 0x20);\n        }\n        uint256 len_ = newView.len();\n        uint256 footprint_ = newView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    // ══════════════════════════════════════════ INSPECTING MEMORY VIEW ═══════════════════════════════════════════════\n\n    /**\n     * @notice Returns the memory address of the underlying bytes.\n     * @param memView       The memory view\n     * @return loc_         The memory address\n     */\n    function loc(MemView memView) internal pure returns (uint256 loc_) {\n        // loc is stored in the highest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u003e\u003e 128;\n    }\n\n    /**\n     * @notice Returns the number of bytes of the view.\n     * @param memView       The memory view\n     * @return len_         The length of the view\n     */\n    function len(MemView memView) internal pure returns (uint256 len_) {\n        // len is stored in the lowest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u0026 type(uint128).max;\n    }\n\n    /**\n     * @notice Returns the endpoint of `memView`.\n     * @param memView       The memory view\n     * @return end_         The endpoint of `memView`\n     */\n    function end(MemView memView) internal pure returns (uint256 end_) {\n        // The endpoint never overflows uint128, let alone uint256, so we could use unchecked math here\n        unchecked {\n            return memView.loc() + memView.len();\n        }\n    }\n\n    /**\n     * @notice Returns the number of memory words this memory view occupies, rounded up.\n     * @param memView       The memory view\n     * @return words_       The number of memory words\n     */\n    function words(MemView memView) internal pure returns (uint256 words_) {\n        // returning ceil(length / 32.0)\n        unchecked {\n            return (memView.len() + 31) \u003e\u003e 5;\n        }\n    }\n\n    /**\n     * @notice Returns the in-memory footprint of a fresh copy of the view.\n     * @param memView       The memory view\n     * @return footprint_   The in-memory footprint of a fresh copy of the view.\n     */\n    function footprint(MemView memView) internal pure returns (uint256 footprint_) {\n        // words() * 32\n        return memView.words() \u003c\u003c 5;\n    }\n\n    // ════════════════════════════════════════════ HASHING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the keccak256 hash of the underlying memory\n     * @param memView       The memory view\n     * @return digest       The keccak256 hash of the underlying memory\n     */\n    function keccak(MemView memView) internal pure returns (bytes32 digest) {\n        uint256 loc_ = memView.loc();\n        uint256 len_ = memView.len();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            digest := keccak256(loc_, len_)\n        }\n    }\n\n    /**\n     * @notice Adds a salt to the keccak256 hash of the underlying data and returns the keccak256 hash of the\n     * resulting data.\n     * @param memView       The memory view\n     * @return digestSalted keccak256(salt, keccak256(memView))\n     */\n    function keccakSalted(MemView memView, bytes32 salt) internal pure returns (bytes32 digestSalted) {\n        return keccak256(bytes.concat(salt, memView.keccak()));\n    }\n\n    // ════════════════════════════════════════════ SLICING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Safe slicing without memory modification.\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the given index\n     */\n    function slice(MemView memView, uint256 index_, uint256 len_) internal pure returns (MemView) {\n        uint256 loc_ = memView.loc();\n        // Ensure it doesn't overrun the view\n        if (loc_ + index_ + len_ \u003e memView.end()) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // loc_ + index_ \u003c= memView.end()\n            return build({loc_: loc_ + index_, len_: len_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing bytes from `index` to end(memView).\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @return The new view for the slice starting from the given index until the initial view endpoint\n     */\n    function sliceFrom(MemView memView, uint256 index_) internal pure returns (MemView) {\n        uint256 len_ = memView.len();\n        // Ensure it doesn't overrun the view\n        if (index_ \u003e len_) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // index_ \u003c= len_ =\u003e memView.loc() + index_ \u003c= memView.loc() + memView.len() == memView.end()\n            return build({loc_: memView.loc() + index_, len_: len_ - index_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the first `len` bytes.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the initial view beginning\n     */\n    function prefix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        return memView.slice({index_: 0, len_: len_});\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the last `len` byte.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length until the initial view endpoint\n     */\n    function postfix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        uint256 viewLen = memView.len();\n        // Ensure it doesn't overrun the view\n        if (len_ \u003e viewLen) {\n            revert ViewOverrun();\n        }\n        // Could do the unchecked math due to the check above\n        uint256 index_;\n        unchecked {\n            index_ = viewLen - len_;\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // len_ \u003c= memView.len() =\u003e memView.loc() \u003c= loc_ \u003c= memView.end()\n            return build({loc_: memView.loc() + viewLen - len_, len_: len_});\n        }\n    }\n\n    // ═══════════════════════════════════════════ INDEXING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Load up to 32 bytes from the view onto the stack.\n     * @dev Returns a bytes32 with only the `bytes_` HIGHEST bytes set.\n     * This can be immediately cast to a smaller fixed-length byte array.\n     * To automatically cast to an integer, use `indexUint`.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return result       The 32 byte result having only `bytes_` highest bytes set\n     */\n    function index(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (bytes32 result) {\n        if (bytes_ == 0) {\n            return bytes32(0);\n        }\n        // Can't load more than 32 bytes to the stack in one go\n        if (bytes_ \u003e 32) {\n            revert IndexedTooMuch();\n        }\n        // The last indexed byte should be within view boundaries\n        if (index_ + bytes_ \u003e memView.len()) {\n            revert ViewOverrun();\n        }\n        uint256 bitLength = bytes_ \u003c\u003c 3; // bytes_ * 8\n        uint256 loc_ = memView.loc();\n        // Get a mask with `bitLength` highest bits set\n        uint256 mask;\n        // 0x800...00 binary representation is 100...00\n        // sar stands for \"signed arithmetic shift\": https://en.wikipedia.org/wiki/Arithmetic_shift\n        // sar(N-1, 100...00) = 11...100..00, with exactly N highest bits set to 1\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            mask := sar(sub(bitLength, 1), 0x8000000000000000000000000000000000000000000000000000000000000000)\n        }\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load a full word using index offset, and apply mask to ignore non-relevant bytes\n            result := and(mload(add(loc_, index_)), mask)\n        }\n    }\n\n    /**\n     * @notice Parse an unsigned integer from the view at `index`.\n     * @dev Requires that the view have \u003e= `bytes_` bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return The unsigned integer\n     */\n    function indexUint(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (uint256) {\n        bytes32 indexedBytes = memView.index(index_, bytes_);\n        // `index()` returns left-aligned `bytes_`, while integers are right-aligned\n        // Shifting here to right-align with the full 32 bytes word: need to shift right `(32 - bytes_)` bytes\n        unchecked {\n            // memView.index() reverts when bytes_ \u003e 32, thus unchecked math\n            return uint256(indexedBytes) \u003e\u003e ((32 - bytes_) \u003c\u003c 3);\n        }\n    }\n\n    /**\n     * @notice Parse an address from the view at `index`.\n     * @dev Requires that the view have \u003e= 20 bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @return The address\n     */\n    function indexAddress(MemView memView, uint256 index_) internal pure returns (address) {\n        // index 20 bytes as `uint160`, and then cast to `address`\n        return address(uint160(memView.indexUint(index_, 20)));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns a memory view over the specified memory location\n    /// without checking if it points to unallocated memory.\n    function _unsafeBuildUnchecked(uint256 loc_, uint256 len_) private pure returns (MemView) {\n        // There is no scenario where loc or len would overflow uint128, so we omit this check.\n        // We use the highest 128 bits to encode the location and the lowest 128 bits to encode the length.\n        return MemView.wrap((loc_ \u003c\u003c 128) | len_);\n    }\n\n    /**\n     * @notice Copy the view to a location, return an unsafe memory reference\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memView       The memory view\n     * @param newLoc        The new location to copy the underlying view data\n     * @return The memory view over the unsafe memory with the copied underlying data\n     */\n    function _unsafeCopyTo(MemView memView, uint256 newLoc) private view returns (MemView) {\n        uint256 len_ = memView.len();\n        uint256 oldLoc = memView.loc();\n\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (newLoc \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        bool res;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // use the identity precompile (0x04) to copy\n            res := staticcall(gas(), 0x04, oldLoc, len_, newLoc, len_)\n        }\n        if (!res) revert PrecompileOutOfGas();\n        return _unsafeBuildUnchecked({loc_: newLoc, len_: len_});\n    }\n\n    /**\n     * @notice Join the views in memory, return an unsafe reference to the memory.\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memViews      The memory views\n     * @return The conjoined view pointing to the new memory\n     */\n    function _unsafeJoin(MemView[] memory memViews, uint256 location) private view returns (MemView) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (location \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        // Copy the views to the specified location one by one, by tracking the amount of copied bytes so far\n        uint256 offset = 0;\n        for (uint256 i = 0; i \u003c memViews.length;) {\n            MemView memView = memViews[i];\n            // We can use the unchecked math here as location + sum(view.length) will never overflow uint256\n            unchecked {\n                _unsafeCopyTo(memView, location + offset);\n                offset += memView.len();\n                ++i;\n            }\n        }\n        return _unsafeBuildUnchecked({loc_: location, len_: offset});\n    }\n}\n\n// contracts/libs/merkle/MerkleMath.sol\n\nlibrary MerkleMath {\n    // ═════════════════════════════════════════ BASIC MERKLE CALCULATIONS ═════════════════════════════════════════════\n\n    /**\n     * @notice Calculates the merkle root for the given leaf and merkle proof.\n     * @dev Will revert if proof length exceeds the tree height.\n     * @param index     Index of `leaf` in tree\n     * @param leaf      Leaf of the merkle tree\n     * @param proof     Proof of inclusion of `leaf` in the tree\n     * @param height    Height of the merkle tree\n     * @return root_    Calculated Merkle Root\n     */\n    function proofRoot(uint256 index, bytes32 leaf, bytes32[] memory proof, uint256 height)\n        internal\n        pure\n        returns (bytes32 root_)\n    {\n        // Proof length could not exceed the tree height\n        uint256 proofLen = proof.length;\n        if (proofLen \u003e height) revert TreeHeightTooLow();\n        root_ = leaf;\n        /// @dev Apply unchecked to all ++h operations\n        unchecked {\n            // Go up the tree levels from the leaf following the proof\n            for (uint256 h = 0; h \u003c proofLen; ++h) {\n                // Get a sibling node on current level: this is proof[h]\n                root_ = getParent(root_, proof[h], index, h);\n            }\n            // Go up to the root: the remaining siblings are EMPTY\n            for (uint256 h = proofLen; h \u003c height; ++h) {\n                root_ = getParent(root_, bytes32(0), index, h);\n            }\n        }\n    }\n\n    /**\n     * @notice Calculates the parent of a node on the path from one of the leafs to root.\n     * @param node          Node on a path from tree leaf to root\n     * @param sibling       Sibling for a given node\n     * @param leafIndex     Index of the tree leaf\n     * @param nodeHeight    \"Level height\" for `node` (ZERO for leafs, ORIGIN_TREE_HEIGHT for root)\n     */\n    function getParent(bytes32 node, bytes32 sibling, uint256 leafIndex, uint256 nodeHeight)\n        internal\n        pure\n        returns (bytes32 parent)\n    {\n        // Index for `node` on its \"tree level\" is (leafIndex / 2**height)\n        // \"Left child\" has even index, \"right child\" has odd index\n        if ((leafIndex \u003e\u003e nodeHeight) \u0026 1 == 0) {\n            // Left child\n            return getParent(node, sibling);\n        } else {\n            // Right child\n            return getParent(sibling, node);\n        }\n    }\n\n    /// @notice Calculates the parent of tow nodes in the merkle tree.\n    /// @dev We use implementation with H(0,0) = 0\n    /// This makes EVERY empty node in the tree equal to ZERO,\n    /// saving us from storing H(0,0), H(H(0,0), H(0, 0)), and so on\n    /// @param leftChild    Left child of the calculated node\n    /// @param rightChild   Right child of the calculated node\n    /// @return parent      Value for the node having above mentioned children\n    function getParent(bytes32 leftChild, bytes32 rightChild) internal pure returns (bytes32 parent) {\n        if (leftChild == bytes32(0) \u0026\u0026 rightChild == bytes32(0)) {\n            return 0;\n        } else {\n            return keccak256(bytes.concat(leftChild, rightChild));\n        }\n    }\n\n    // ════════════════════════════════ ROOT/PROOF CALCULATION FOR A LIST OF LEAFS ═════════════════════════════════════\n\n    /**\n     * @notice Calculates merkle root for a list of given leafs.\n     * Merkle Tree is constructed by padding the list with ZERO values for leafs until list length is `2**height`.\n     * Merkle Root is calculated for the constructed tree, and then saved in `leafs[0]`.\n     * \u003e Note:\n     * \u003e - `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * \u003e - Caller is expected not to reuse `hashes` list after the call, and only use `leafs[0]` value,\n     * which is guaranteed to contain the calculated merkle root.\n     * \u003e - root is calculated using the `H(0,0) = 0` Merkle Tree implementation. See MerkleTree.sol for details.\n     * @dev Amount of leaves should be at most `2**height`\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param height    Height of the Merkle Tree to construct\n     */\n    function calculateRoot(bytes32[] memory hashes, uint256 height) internal pure {\n        uint256 levelLength = hashes.length;\n        // Amount of hashes could not exceed amount of leafs in tree with the given height\n        if (levelLength \u003e (1 \u003c\u003c height)) revert TreeHeightTooLow();\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\": the amount of iterations for the for loop above.\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n            }\n        }\n    }\n\n    /**\n     * @notice Generates a proof of inclusion of a leaf in the list. If the requested index is outside\n     * of the list range, generates a proof of inclusion for an empty leaf (proof of non-inclusion).\n     * The Merkle Tree is constructed by padding the list with ZERO values until list length is a power of two\n     * __AND__ index is in the extended list range. For example:\n     *  - `hashes.length == 6` and `0 \u003c= index \u003c= 7` will \"extend\" the list to 8 entries.\n     *  - `hashes.length == 6` and `7 \u003c index \u003c= 15` will \"extend\" the list to 16 entries.\n     * \u003e Note: `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * Caller is expected not to reuse `hashes` list after the call.\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param index     Leaf index to generate the proof for\n     * @return proof    Generated merkle proof\n     */\n    function calculateProof(bytes32[] memory hashes, uint256 index) internal pure returns (bytes32[] memory proof) {\n        // Use only meaningful values for the shortened proof\n        // Check if index is within the list range (we want to generates proofs for outside leafs as well)\n        uint256 height = getHeight(index \u003c hashes.length ? hashes.length : (index + 1));\n        proof = new bytes32[](height);\n        uint256 levelLength = hashes.length;\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Use sibling for the merkle proof; `index^1` is index of our sibling\n                proof[h] = (index ^ 1 \u003c levelLength) ? hashes[index ^ 1] : bytes32(0);\n\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\"\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n                // Traverse to parent node\n                index \u003e\u003e= 1;\n            }\n        }\n    }\n\n    /// @notice Returns the height of the tree having a given amount of leafs.\n    function getHeight(uint256 leafs) internal pure returns (uint256 height) {\n        uint256 amount = 1;\n        while (amount \u003c leafs) {\n            unchecked {\n                ++height;\n            }\n            amount \u003c\u003c= 1;\n        }\n    }\n}\n\n// contracts/libs/stack/GasData.sol\n\n/// GasData in encoded data with \"basic information about gas prices\" for some chain.\ntype GasData is uint96;\n\nusing GasDataLib for GasData global;\n\n/// ChainGas is encoded data with given chain's \"basic information about gas prices\".\ntype ChainGas is uint128;\n\nusing GasDataLib for ChainGas global;\n\n/// Library for encoding and decoding GasData and ChainGas structs.\n/// # GasData\n/// `GasData` is a struct to store the \"basic information about gas prices\", that could\n/// be later used to approximate the cost of a message execution, and thus derive the\n/// minimal tip values for sending a message to the chain.\n/// \u003e - `GasData` is supposed to be cached by `GasOracle` contract, allowing to store the\n/// \u003e approximates instead of the exact values, and thus save on storage costs.\n/// \u003e - For instance, if `GasOracle` only updates the values on +- 10% change, having an\n/// \u003e 0.4% error on the approximates would be acceptable.\n/// `GasData` is supposed to be included in the Origin's state, which are synced across\n/// chains using Agent-signed snapshots and attestations.\n/// ## GasData stack layout (from highest bits to lowest)\n///\n/// | Position   | Field        | Type   | Bytes | Description                                         |\n/// | ---------- | ------------ | ------ | ----- | --------------------------------------------------- |\n/// | (012..010] | gasPrice     | uint16 | 2     | Gas price for the chain (in Wei per gas unit)       |\n/// | (010..008] | dataPrice    | uint16 | 2     | Calldata price (in Wei per byte of content)         |\n/// | (008..006] | execBuffer   | uint16 | 2     | Tx fee safety buffer for message execution (in Wei) |\n/// | (006..004] | amortAttCost | uint16 | 2     | Amortized cost for attestation submission (in Wei)  |\n/// | (004..002] | etherPrice   | uint16 | 2     | Chain's Ether Price / Mainnet Ether Price (in BWAD) |\n/// | (002..000] | markup       | uint16 | 2     | Markup for the message execution (in BWAD)          |\n/// \u003e See Number.sol for more details on `Number` type and BWAD (binary WAD) math.\n///\n/// ## ChainGas stack layout (from highest bits to lowest)\n///\n/// | Position   | Field   | Type   | Bytes | Description      |\n/// | ---------- | ------- | ------ | ----- | ---------------- |\n/// | (016..004] | gasData | uint96 | 12    | Chain's gas data |\n/// | (004..000] | domain  | uint32 | 4     | Chain's domain   |\nlibrary GasDataLib {\n    /// @dev Amount of bits to shift to gasPrice field\n    uint96 private constant SHIFT_GAS_PRICE = 10 * 8;\n    /// @dev Amount of bits to shift to dataPrice field\n    uint96 private constant SHIFT_DATA_PRICE = 8 * 8;\n    /// @dev Amount of bits to shift to execBuffer field\n    uint96 private constant SHIFT_EXEC_BUFFER = 6 * 8;\n    /// @dev Amount of bits to shift to amortAttCost field\n    uint96 private constant SHIFT_AMORT_ATT_COST = 4 * 8;\n    /// @dev Amount of bits to shift to etherPrice field\n    uint96 private constant SHIFT_ETHER_PRICE = 2 * 8;\n\n    /// @dev Amount of bits to shift to gasData field\n    uint128 private constant SHIFT_GAS_DATA = 4 * 8;\n\n    // ═════════════════════════════════════════════════ GAS DATA ══════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded GasData struct with the given fields.\n    /// @param gasPrice_        Gas price for the chain (in Wei per gas unit)\n    /// @param dataPrice_       Calldata price (in Wei per byte of content)\n    /// @param execBuffer_      Tx fee safety buffer for message execution (in Wei)\n    /// @param amortAttCost_    Amortized cost for attestation submission (in Wei)\n    /// @param etherPrice_      Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n    /// @param markup_          Markup for the message execution (in BWAD)\n    function encodeGasData(\n        Number gasPrice_,\n        Number dataPrice_,\n        Number execBuffer_,\n        Number amortAttCost_,\n        Number etherPrice_,\n        Number markup_\n    ) internal pure returns (GasData) {\n        // Number type wraps uint16, so could safely be casted to uint96\n        // forgefmt: disable-next-item\n        return GasData.wrap(\n            uint96(Number.unwrap(gasPrice_)) \u003c\u003c SHIFT_GAS_PRICE |\n            uint96(Number.unwrap(dataPrice_)) \u003c\u003c SHIFT_DATA_PRICE |\n            uint96(Number.unwrap(execBuffer_)) \u003c\u003c SHIFT_EXEC_BUFFER |\n            uint96(Number.unwrap(amortAttCost_)) \u003c\u003c SHIFT_AMORT_ATT_COST |\n            uint96(Number.unwrap(etherPrice_)) \u003c\u003c SHIFT_ETHER_PRICE |\n            uint96(Number.unwrap(markup_))\n        );\n    }\n\n    /// @notice Wraps padded uint256 value into GasData struct.\n    function wrapGasData(uint256 paddedGasData) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(paddedGasData));\n    }\n\n    /// @notice Returns the gas price, in Wei per gas unit.\n    function gasPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_GAS_PRICE));\n    }\n\n    /// @notice Returns the calldata price, in Wei per byte of content.\n    function dataPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_DATA_PRICE));\n    }\n\n    /// @notice Returns the tx fee safety buffer for message execution, in Wei.\n    function execBuffer(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_EXEC_BUFFER));\n    }\n\n    /// @notice Returns the amortized cost for attestation submission, in Wei.\n    function amortAttCost(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_AMORT_ATT_COST));\n    }\n\n    /// @notice Returns the ratio of Chain's Ether Price / Mainnet Ether Price, in BWAD math.\n    function etherPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_ETHER_PRICE));\n    }\n\n    /// @notice Returns the markup for the message execution, in BWAD math.\n    function markup(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data)));\n    }\n\n    // ════════════════════════════════════════════════ CHAIN DATA ═════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded ChainGas struct with the given fields.\n    /// @param gasData_ Chain's gas data\n    /// @param domain_  Chain's domain\n    function encodeChainGas(GasData gasData_, uint32 domain_) internal pure returns (ChainGas) {\n        // GasData type wraps uint96, so could safely be casted to uint128\n        return ChainGas.wrap(uint128(GasData.unwrap(gasData_)) \u003c\u003c SHIFT_GAS_DATA | uint128(domain_));\n    }\n\n    /// @notice Wraps padded uint256 value into ChainGas struct.\n    function wrapChainGas(uint256 paddedChainGas) internal pure returns (ChainGas) {\n        // Casting to uint128 will truncate the highest bits, which is the behavior we want\n        return ChainGas.wrap(uint128(paddedChainGas));\n    }\n\n    /// @notice Returns the chain's gas data.\n    function gasData(ChainGas data) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(ChainGas.unwrap(data) \u003e\u003e SHIFT_GAS_DATA));\n    }\n\n    /// @notice Returns the chain's domain.\n    function domain(ChainGas data) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(ChainGas.unwrap(data));\n    }\n\n    /// @notice Returns the hash for the list of ChainGas structs.\n    function snapGasHash(ChainGas[] memory snapGas) internal pure returns (bytes32 snapGasHash_) {\n        // Use assembly to calculate the hash of the array without copying it\n        // ChainGas takes a single word of storage, thus ChainGas[] is stored in the following way:\n        // 0x00: length of the array, in words\n        // 0x20: first ChainGas struct\n        // 0x40: second ChainGas struct\n        // And so on...\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Find the location where the array data starts, we add 0x20 to skip the length field\n            let loc := add(snapGas, 0x20)\n            // Load the length of the array (in words).\n            // Shifting left 5 bits is equivalent to multiplying by 32: this converts from words to bytes.\n            let len := shl(5, mload(snapGas))\n            // Calculate the hash of the array\n            snapGasHash_ := keccak256(loc, len)\n        }\n    }\n}\n\n// contracts/libs/stack/Header.sol\n\n/// Header is encoded data with \"general routing information\".\ntype Header is uint136;\n\nusing HeaderLib for Header global;\n\n/// Types of messages supported by Origin-Destination\n/// - Base: message sent by protocol user, contains tips\n/// - Manager: message sent between AgentManager contracts located on different chains, no tips\nenum MessageFlag {\n    Base,\n    Manager\n}\n\nusing HeaderLib for MessageFlag global;\n\n/// Library for formatting _the header part_ of _the messages used by Origin and Destination_.\n/// - Header represents general information for routing a Message for Origin and Destination.\n/// - Header occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n///\n/// # Header stack layout (from highest bits to lowest)\n///\n/// | Position   | Field            | Type   | Bytes | Description                             |\n/// | ---------- | ---------------- | ------ | ----- | --------------------------------------- |\n/// | (017..016] | flag             | uint8  | 1     | Flag specifying the type of message     |\n/// | (016..012] | origin           | uint32 | 4     | Domain where message originated         |\n/// | (012..008] | nonce            | uint32 | 4     | Message nonce on the origin domain      |\n/// | (008..004] | destination      | uint32 | 4     | Domain where message will be executed   |\n/// | (004..000] | optimisticPeriod | uint32 | 4     | Optimistic period that will be enforced |\nlibrary HeaderLib {\n    /// @dev Amount of bits to shift to flag field\n    uint136 private constant SHIFT_FLAG = 16 * 8;\n    /// @dev Amount of bits to shift to origin field\n    uint136 private constant SHIFT_ORIGIN = 12 * 8;\n    /// @dev Amount of bits to shift to nonce field\n    uint136 private constant SHIFT_NONCE = 8 * 8;\n    /// @dev Amount of bits to shift to destination field\n    uint136 private constant SHIFT_DESTINATION = 4 * 8;\n\n    /// @notice Returns an encoded header with provided fields\n    /// @param origin_              Domain of origin chain\n    /// @param nonce_               Message nonce on origin chain\n    /// @param destination_         Domain of destination chain\n    /// @param optimisticPeriod_    Optimistic period for message execution\n    function encodeHeader(\n        MessageFlag flag_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint32 destination_,\n        uint32 optimisticPeriod_\n    ) internal pure returns (Header) {\n        // All casts below are upcasts, so they are safe\n        // forgefmt: disable-next-item\n        return Header.wrap(\n            uint136(uint8(flag_)) \u003c\u003c SHIFT_FLAG |\n            uint136(origin_) \u003c\u003c SHIFT_ORIGIN |\n            uint136(nonce_) \u003c\u003c SHIFT_NONCE |\n            uint136(destination_) \u003c\u003c SHIFT_DESTINATION |\n            uint136(optimisticPeriod_)\n        );\n    }\n\n    /// @notice Checks that the header is a valid encoded header.\n    function isHeader(uint256 paddedHeader) internal pure returns (bool) {\n        // Check that flag is within range\n        return _flag(paddedHeader) \u003c= uint8(type(MessageFlag).max);\n    }\n\n    /// @notice Wraps the padded encoded request into a Header-typed value.\n    /// @dev The \"padded\" header is simply an encoded header casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded headers\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedHeader) internal pure returns (Header) {\n        // Check that flag is within range\n        if (!isHeader(paddedHeader)) revert FlagOutOfRange();\n        // Casting to uint136 will truncate the highest bits, which is the behavior we want\n        return Header.wrap(uint136(paddedHeader));\n    }\n\n    /// @notice Returns header's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Header header) internal pure returns (bytes32 hashedHeader) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store header in scratch space\n            mstore(0, header)\n            // Compute hash of header padded to 32 bytes\n            hashedHeader := keccak256(0, 32)\n        }\n    }\n\n    // ══════════════════════════════════════════════ HEADER SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns header's flag field\n    function flag(Header header) internal pure returns (MessageFlag) {\n        // We check that flag is within range when wrapping the header, so this cast is safe\n        return MessageFlag(_flag(Header.unwrap(header)));\n    }\n\n    /// @notice Returns header's origin field\n    function origin(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_ORIGIN);\n    }\n\n    /// @notice Returns header's nonce field\n    function nonce(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_NONCE);\n    }\n\n    /// @notice Returns header's destination field\n    function destination(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_DESTINATION);\n    }\n\n    /// @notice Returns header's optimistic seconds field\n    function optimisticPeriod(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns header's flag field without casting to MessageFlag\n    function _flag(uint256 paddedHeader) private pure returns (uint8) {\n        // Casting to uint8 will truncate the highest bits, which is the behavior we want\n        return uint8(paddedHeader \u003e\u003e SHIFT_FLAG);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n     * constructor.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall \u0026\u0026 _initialized \u003c 1) || (!AddressUpgradeable.isContract(address(this)) \u0026\u0026 _initialized == 1),\n            \"Initializable: contract is already initialized\"\n        );\n        _initialized = 1;\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: setting the version to 255 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing \u0026\u0026 _initialized \u003c version, \"Initializable: contract is already initialized\");\n        _initialized = version;\n        _initializing = true;\n        _;\n        _initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        require(_initializing, \"Initializable: contract is not initializing\");\n        _;\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized != type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint8) {\n        return _initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _initializing;\n    }\n}\n\n// contracts/interfaces/IAgentManager.sol\n\ninterface IAgentManager {\n    /**\n     * @notice Allows Inbox to open a Dispute between a Guard and a Notary, if they are both not in Dispute already.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Guard or Notary is already in Dispute.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Allows Inbox to slash an agent, if their fraud was proven.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Domain doesn't match the saved agent domain.\n     * @param domain    Domain where the Agent is active\n     * @param agent     Address of the Agent\n     * @param prover    Address that initially provided fraud proof\n     */\n    function slashAgent(uint32 domain, address agent, address prover) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest known root of the Agent Merkle Tree.\n     */\n    function agentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns the number of opened Disputes.\n     * @dev This includes the Disputes that have been resolved already.\n     */\n    function getDisputesAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns information about the dispute with the given index.\n     * @dev Will revert if dispute with given index hasn't been opened yet.\n     * @param index             Dispute index\n     * @return guard            Address of the Guard in the Dispute\n     * @return notary           Address of the Notary in the Dispute\n     * @return slashedAgent     Address of the Agent who was slashed when Dispute was resolved\n     * @return fraudProver      Address who provided fraud proof to resolve the Dispute\n     * @return reportPayload    Raw payload with report data that led to the Dispute\n     * @return reportSignature  Guard signature for the report payload\n     */\n    function getDispute(uint256 index)\n        external\n        view\n        returns (\n            address guard,\n            address notary,\n            address slashedAgent,\n            address fraudProver,\n            bytes memory reportPayload,\n            bytes memory reportSignature\n        );\n\n    /**\n     * @notice Returns the current Dispute status of a given agent. See Structures.sol for details.\n     * @dev Every returned value will be set to zero if agent was not slashed and is not in Dispute.\n     * `rival` and `disputePtr` will be set to zero if the agent was slashed without being in Dispute.\n     * @param agent         Agent address\n     * @return flag         Flag describing the current Dispute status for the agent: None/Pending/Slashed\n     * @return rival        Address of the rival agent in the Dispute\n     * @return fraudProver  Address who provided fraud proof to resolve the Dispute\n     * @return disputePtr   Index of the opened Dispute PLUS ONE. Zero if agent is not in Dispute.\n     */\n    function disputeStatus(address agent)\n        external\n        view\n        returns (DisputeFlag flag, address rival, address fraudProver, uint256 disputePtr);\n}\n\n// contracts/interfaces/IAgentSecured.sol\n\ninterface IAgentSecured {\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * between a Guard and a Notary has been opened.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * has been resolved due to one of the agents being slashed.\n     * \u003e `rivalIndex` will be ZERO, if the slashed agent was not in the Dispute.\n     * @param slashedIndex  Index of the slashed agent in the Agent Merkle Tree\n     * @param rivalIndex    Index of the their Dispute Rival in the Agent Merkle Tree\n     */\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the address of the local AgentManager contract, which is treated as\n     * the \"source of truth\" for agent statuses.\n     */\n    function agentManager() external view returns (address);\n\n    /**\n     * @notice Returns the address of the local Inbox contract, which is treated as\n     * the \"source of truth\" for agent-signed statements.\n     * @dev Inbox passes verified agent statements to `IAgentSecured` contract.\n     */\n    function inbox() external view returns (address);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns (flag, openedAt, resolvedAt) that describes the latest status of\n     * the latest dispute for an agent with a given index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param agentIndex    Agent index in the Agent Merkle Tree\n     * @return              Latest dispute status for the given agent: (flag, openedAt, resolvedAt)\n     */\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory);\n}\n\n// contracts/libs/memory/ByteString.sol\n\n/// @dev CallData is a memory view over the payload to be used for an external call, i.e.\n/// recipient.call(callData). Its length is always (4 + 32 * N) bytes:\n/// - First 4 bytes represent the function selector.\n/// - 32 * N bytes represent N words that function arguments occupy.\ntype CallData is uint256;\n\n/// @dev Attach library functions to CallData\nusing ByteString for CallData global;\n\n/// @dev Signature is a memory view over a \"65 bytes\" array representing a ECDSA signature.\ntype Signature is uint256;\n\n/// @dev Attach library functions to Signature\nusing ByteString for Signature global;\n\nlibrary ByteString {\n    using MemViewLib for bytes;\n\n    /**\n     * @dev non-compact ECDSA signatures are enforced as of OZ 4.7.3\n     *\n     *      Signature payload memory layout\n     * [000 .. 032) r   bytes32 32 bytes\n     * [032 .. 064) s   bytes32 32 bytes\n     * [064 .. 065) v   uint8    1 byte\n     */\n    uint256 internal constant SIGNATURE_LENGTH = 65;\n    uint256 private constant OFFSET_R = 0;\n    uint256 private constant OFFSET_S = 32;\n    uint256 private constant OFFSET_V = 64;\n\n    /**\n     * @dev Calldata memory layout\n     * [000 .. 004) selector    bytes4  4 bytes\n     *      Optional: N function arguments\n     * [004 .. 036) arg1        bytes32 32 bytes\n     *      ..\n     * [AAA .. END) argN        bytes32 32 bytes\n     */\n    uint256 internal constant SELECTOR_LENGTH = 4;\n    uint256 private constant OFFSET_SELECTOR = 0;\n    uint256 private constant OFFSET_ARGUMENTS = SELECTOR_LENGTH;\n\n    // ═════════════════════════════════════════════════ SIGNATURE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the signature payload from the given values.\n     * @dev Using ByteString.formatSignature({r: r, s: s, v: v}) will make sure\n     * that params are given in the right order.\n     */\n    function formatSignature(bytes32 r, bytes32 s, uint8 v) internal pure returns (bytes memory) {\n        return abi.encodePacked(r, s, v);\n    }\n\n    /**\n     * @notice Returns a Signature view over for the given payload.\n     * @dev Will revert if the payload is not a signature.\n     */\n    function castToSignature(bytes memory payload) internal pure returns (Signature) {\n        return castToSignature(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Signature view.\n     * @dev Will revert if the memory view is not over a signature.\n     */\n    function castToSignature(MemView memView) internal pure returns (Signature) {\n        if (!isSignature(memView)) revert UnformattedSignature();\n        return Signature.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a signature\n     */\n    function isSignature(MemView memView) internal pure returns (bool) {\n        return memView.len() == SIGNATURE_LENGTH;\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Signature signature) internal pure returns (MemView) {\n        return MemView.wrap(Signature.unwrap(signature));\n    }\n\n    // ═════════════════════════════════════════════ SIGNATURE SLICING ═════════════════════════════════════════════════\n\n    /// @notice Unpacks signature payload into (r, s, v) parameters.\n    /// @dev Make sure to verify signature length with isSignature() beforehand.\n    function toRSV(Signature signature) internal pure returns (bytes32 r, bytes32 s, uint8 v) {\n        // Get the underlying memory view\n        MemView memView = unwrap(signature);\n        r = memView.index({index_: OFFSET_R, bytes_: 32});\n        s = memView.index({index_: OFFSET_S, bytes_: 32});\n        // Can be safely casted to uint8, since we index a single byte\n        v = uint8(memView.indexUint({index_: OFFSET_V, bytes_: 1}));\n    }\n\n    // ═════════════════════════════════════════════════ CALLDATA ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the calldata with the modified arguments:\n     * the existing arguments are prepended with the arguments from the prefix.\n     * @dev Given:\n     *  - `calldata = abi.encodeWithSelector(foo.selector, d, e);`\n     *  - `prefix = abi.encode(a, b, c);`\n     *  - `a`, `b`, `c` are arguments of static type (i.e. not dynamically sized ones)\n     *      Then:\n     *  - Function will return abi.encodeWithSelector(foo.selector, a, c, c, d, e)\n     *  - Returned calldata will trigger `foo(a, b, c, d, e)` when used for a contract call.\n     * Note: for clarification as to what types are considered static, see\n     * https://docs.soliditylang.org/en/latest/abi-spec.html#formal-specification-of-the-encoding\n     * @param callData  Calldata that needs to be modified\n     * @param prefix    ABI-encoded arguments to use as the first arguments in the new calldata\n     * @return Modified calldata having prefix as the first arguments.\n     */\n    function addPrefix(CallData callData, bytes memory prefix) internal view returns (bytes memory) {\n        // Prefix should occupy a whole amount of words in memory\n        if (!_fullWords(prefix.length)) revert UnformattedCallDataPrefix();\n        MemView[] memory views = new MemView[](3);\n        // Use payload's function selector\n        views[0] = abi.encodePacked(callData.callSelector()).ref();\n        // Use prefix as the first arguments\n        views[1] = prefix.ref();\n        // Use payload's remaining arguments\n        views[2] = callData.arguments();\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a CallData view over for the given payload.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(bytes memory payload) internal pure returns (CallData) {\n        return castToCallData(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a CallData view.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(MemView memView) internal pure returns (CallData) {\n        if (!isCallData(memView)) revert UnformattedCallData();\n        return CallData.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a valid calldata, i.e.\n     * a function selector, followed by arbitrary amount of arguments.\n     */\n    function isCallData(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Calldata should at least have a function selector\n        if (length \u003c SELECTOR_LENGTH) return false;\n        // The remainder of the calldata should be exactly N memory words (N \u003e= 0)\n        return _fullWords(length - SELECTOR_LENGTH);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(CallData callData) internal pure returns (MemView) {\n        return MemView.wrap(CallData.unwrap(callData));\n    }\n\n    /// @notice Returns callData's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(CallData callData) internal pure returns (bytes32) {\n        return callData.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ CALLDATA SLICING ══════════════════════════════════════════════════\n\n    /**\n     * @notice Returns amount of memory words (32 byte chunks) the function arguments\n     * occupy in the calldata.\n     * @dev This might differ from amount of arguments supplied, if any of the arguments\n     * occupies more than one memory slot. It is true, however, that argument part of the payload\n     * occupies exactly N words, even for dynamic types like `bytes`\n     */\n    function argumentWords(CallData callData) internal pure returns (uint256) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        // Equivalent of (length - SELECTOR_LENGTH) / 32\n        return (memView.len() - SELECTOR_LENGTH) \u003e\u003e 5;\n    }\n\n    /// @notice Returns selector for the provided calldata.\n    function callSelector(CallData callData) internal pure returns (bytes4) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return bytes4(memView.index({index_: OFFSET_SELECTOR, bytes_: SELECTOR_LENGTH}));\n    }\n\n    /// @notice Returns abi encoded arguments for the provided calldata.\n    function arguments(CallData callData) internal pure returns (MemView) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return memView.sliceFrom({index_: OFFSET_ARGUMENTS});\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if length is full amount of memory words (32 bytes).\n    function _fullWords(uint256 length) internal pure returns (bool) {\n        // The equivalent of length % 32 == 0\n        return length \u0026 31 == 0;\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n    function __Context_init() internal onlyInitializing {\n    }\n\n    function __Context_init_unchained() internal onlyInitializing {\n    }\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[50] private __gap;\n}\n\n// contracts/libs/merkle/MerkleTree.sol\n\n/// `BaseTree` is a struct representing incremental merkle tree.\n/// - Contains only the current branch.\n/// - The number of inserted leaves is stored externally, and is later supplied for tree operations.\n/// - Has a fixed height of `ORIGIN_TREE_HEIGHT`.\n/// - Can store up to `2 ** ORIGIN_TREE_HEIGHT - 1` leaves.\n/// \u003e Note: the hash function for the tree `H(x, y)` is defined as:\n/// \u003e - `H(0,0) = 0`\n/// \u003e - `H(x,y) = keccak256(x, y), when (x != 0 || y != 0)`\n/// ## Invariant for leafs\n/// - The leftmost empty leaf has `index == count`, where `count` is the amount of the inserted leafs so far.\n/// - Value for any empty leaf or node is bytes32(0).\n/// ## Invariant for current branch\n/// `branch[i]` is always the value of a node on the i-th level.\n/// Levels are numbered from leafs to root: `0 .. ORIGIN_TREE_HEIGHT`.\n/// `branch[i]` stores the value for the node, such that:\n//  - The node is a \"left child\" (e.g. has an even index).\n/// - The node must have two non-empty children.\n/// - Out of all level's \"left child\" nodes with \"non-empty children\",\n/// the one with the biggest index (the rightmost one) is stored as `branch[i]`.\n/// \u003e __`branch` could be used to form a proof of inclusion for the first empty leaf (`index == count`).__\n/// _Here is how:_\n/// - Let's walk along the path from the \"first empty leaf\" to the root.\n/// - i-th bit of the \"first empty leaf\" index (which is equal to `count`) determines if the path's node\n/// for this i-th level is a \"left child\" or a \"right child\".\n/// - i-th bit in `count` is 0 → we are the left child on this level → sibling is the right child\n/// that does not exist yet → `proof[i] = bytes32(0)`.\n/// - i-th bit in `count` is 1 → we are the right child on this level → sibling is the left child\n/// sibling is the rightmost \"left child\" node on the level → `proof[i] = branch[i]`.\n/// \u003e Therefore `proof[i] = (count \u0026 (1 \u003c\u003c i)) == 0 ? bytes32(0) : branch[i])`\nstruct BaseTree {\n    bytes32[ORIGIN_TREE_HEIGHT] branch;\n}\n\nusing MerkleTree for BaseTree global;\n\n/// `HistoricalTree` is an incremental merkle tree keeping track of its historical merkle roots.\n/// \u003e - `roots[N]` is the root of the tree after `N` leafs were inserted\n/// \u003e - `roots[0] == bytes32(0)`\n/// @param tree     Incremental merkle tree\n/// @param roots    Historical merkle roots of the tree\nstruct HistoricalTree {\n    BaseTree tree;\n    bytes32[] roots;\n}\n\nusing MerkleTree for HistoricalTree global;\n\n/// `DynamicTree` is a struct representing a Merkle Tree with `2**AGENT_TREE_HEIGHT` leaves.\n/// - A single operation is available: update value for leaf with an arbitrary index (which might be a non-empty leaf).\n/// - This is done by requesting the proof of inclusion for the old value, which is used to both\n/// verify the old value, and calculate the new root.\n/// \u003e Based on Original idea from [ER forum post](https://ethresear.ch/t/efficient-on-chain-dynamic-merkle-tree/11054).\nstruct DynamicTree {\n    bytes32 root;\n}\n\nusing MerkleTree for DynamicTree global;\n\n/// MerkleTree is work based on Nomad's Merkle.sol, which is used under MIT OR Apache-2.0\n/// [link](https://github.com/nomad-xyz/monorepo/blob/main/packages/contracts-core/contracts/libs/Merkle.sol).\n/// With the following changes:\n/// - Adapted for Solidity 0.8.x.\n/// - Amount of tree leaves stored externally.\n/// - Added thorough documentation.\n/// - `H(0,0) = 0` optimization from [ER forum post](https://ethresear.ch/t/optimizing-sparse-merkle-trees/3751/6).\n/// \u003e Nomad's Merkle.sol is work based on eth2 deposit contract, which is used under CC0-1.0\n///[link](https://github.com/ethereum/deposit_contract/blob/dev/deposit_contract/contracts/validator_registration.v.py).\n/// With the following changes:\n/// \u003e - Implemented in Solidity 0.7.6 (eth2 deposit contract implemented in Vyper).\n/// \u003e - `H() = keccak256()` is used as the hashing function instead of `sha256()`.\nlibrary MerkleTree {\n    /// @dev For root calculation we need at least one empty leaf, thus the minus one in the formula.\n    uint256 internal constant MAX_LEAVES = 2 ** ORIGIN_TREE_HEIGHT - 1;\n\n    // ═════════════════════════════════════════════════ BASE TREE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Inserts `node` into merkle tree\n     * @dev Reverts if tree is full\n     * @param newCount  Amount of inserted leaves in the tree after the insertion (i.e. current + 1)\n     * @param node      Element to insert into tree\n     */\n    function insertBase(BaseTree storage tree, uint256 newCount, bytes32 node) internal {\n        if (newCount \u003e MAX_LEAVES) revert MerkleTreeFull();\n        // We go up the tree following the branch from the empty leaf AFTER the just inserted one.\n        // We stop when we find the first \"right child\" node.\n        // Its sibling is now the rightmost \"left child\" node that has two non-empty children.\n        // Therefore we need to update `tree.branch` value on this level.\n        // One could see that `tree.branch` value on lower and higher levels remain unchanged.\n\n        // Loop invariant: `node` is the current level's value for the branch from JUST INSERTED leaf\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            if ((newCount \u0026 1) == 1) {\n                // Found the first \"right child\" node on the branch from EMPTY leaf\n                // `node` is the value for node on branch from JUST INSERTED leaf\n                // Which in this case is the \"left child\".\n                // We update tree.branch and exit\n                tree.branch[i] = node;\n                return;\n            }\n            // On the branch from EMPTY leaf this is still a \"left child\".\n            // Meaning on branch from JUST INSERTED leaf, `node` is a right child.\n            // We compute value for `node` parent using `tree.branch` invariant:\n            // This is the rightmost \"left child\" node, which would be sibling of `node`.\n            node = MerkleMath.getParent(tree.branch[i], node);\n            // Get the parent index, and go to the next tree level\n            newCount \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n        // As the loop should always end prematurely with the `return` statement,\n        // this code should be unreachable. We assert `false` just to be safe.\n        assert(false);\n    }\n\n    /**\n     * @notice Calculates and returns current root of the merkle tree.\n     * @param count     Current amount of inserted leaves in the tree\n     * @return current  Calculated root of `tree`\n     */\n    function rootBase(BaseTree storage tree, uint256 count) internal view returns (bytes32 current) {\n        // To calculate the root we follow the branch of first EMPTY leaf (index == count)\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            // Check if we are the left or the right child on the current level\n            if ((count \u0026 1) == 1) {\n                // We are the right child. Our sibling is the \"rightmost\" \"left-child\" node\n                // that has two non-empty children → sibling is `tree.branch[i]`\n                current = MerkleMath.getParent(tree.branch[i], current);\n            } else {\n                // We are the left child. Our sibling does not exist yet → sibling is EMPTY\n                current = MerkleMath.getParent(current, bytes32(0));\n            }\n            // Get the parent index, and go to the next tree level\n            count \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    // ══════════════════════════════════════════════ HISTORICAL TREE ══════════════════════════════════════════════════\n\n    /// @notice Initializes the historical roots for the tree by inserting an empty root.\n    // solhint-disable-next-line ordering\n    function initializeRoots(HistoricalTree storage tree) internal returns (bytes32 savedRoot) {\n        // This should only be called once, when the contract is initialized\n        assert(tree.roots.length == 0);\n        // Save root for empty merkle tree: bytes32(0)\n        tree.roots.push(savedRoot);\n    }\n\n    /// @notice Inserts a new leaf into the merkle tree.\n    /// @dev Reverts if tree is full.\n    /// @param node         Element to insert into tree\n    /// @return newRoot     Merkle root after the leaf was inserted\n    function insert(HistoricalTree storage tree, bytes32 node) internal returns (bytes32 newRoot) {\n        // Tree count after the new leaf will be inserted (we store roots[0] as root of empty tree)\n        uint256 newCount = tree.roots.length;\n        tree.tree.insertBase(newCount, node);\n        // Save the new root\n        newRoot = tree.tree.rootBase(newCount);\n        tree.roots.push(newRoot);\n    }\n\n    /// @notice Returns the historical root of the merkle tree.\n    /// @dev Reverts if not enough leafs have been inserted.\n    /// @param count            Amount of leafs in the tree at some point of time\n    /// @return historicalRoot  Merkle root after `count` leafs were inserted\n    function root(HistoricalTree storage tree, uint256 count) internal view returns (bytes32 historicalRoot) {\n        if (count \u003e= tree.roots.length) revert NotEnoughLeafs();\n        return tree.roots[count];\n    }\n\n    // ═══════════════════════════════════════════════ DYNAMIC TREE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Updates the value for the leaf with the given index in the Dynamic Merkle Tree.\n     * @dev Will revert if incorrect proof of inclusion for old value is supplied.\n     * @param tree          Dynamic merkle tree\n     * @param index         Index of the leaf to update\n     * @param oldValue      Previous value of the leaf\n     * @param branch        Proof of inclusion of previous value into the tree\n     * @param newValue      New leaf value to assign\n     * @return newRoot      New value for the Merkle Root after the leaf is updated\n     */\n    function update(\n        DynamicTree storage tree,\n        uint256 index,\n        bytes32 oldValue,\n        bytes32[] memory branch,\n        bytes32 newValue\n    ) internal returns (bytes32 newRoot) {\n        // Check that the old value + proof result in a correct root\n        if (MerkleMath.proofRoot(index, oldValue, branch, AGENT_TREE_HEIGHT) != tree.root) {\n            revert LeafNotProven();\n        }\n        // New root is new value + the same proof (values for sibling nodes are not updated)\n        newRoot = MerkleMath.proofRoot(index, newValue, branch, AGENT_TREE_HEIGHT);\n        // Write the new root\n        tree.root = newRoot;\n    }\n}\n\n// contracts/libs/stack/Tips.sol\n\n/// Tips is encoded data with \"tips paid for sending a base message\".\n/// Note: even though uint256 is also an underlying type for MemView, Tips is stored ON STACK.\ntype Tips is uint256;\n\nusing TipsLib for Tips global;\n\n/// # Tips\n/// Library for formatting _the tips part_ of _the base messages_.\n///\n/// ## How the tips are awarded\n/// Tips are paid for sending a base message, and are split across all the agents that\n/// made the message execution on destination chain possible.\n/// ### Summit tips\n/// Split between:\n///     - Guard posting a snapshot with state ST_G for the origin chain.\n///     - Notary posting a snapshot SN_N using ST_G. This creates attestation A.\n///     - Notary posting a message receipt after it is executed on destination chain.\n/// ### Attestation tips\n/// Paid to:\n///     - Notary posting attestation A to destination chain.\n/// ### Execution tips\n/// Paid to:\n///     - First executor performing a valid execution attempt (correct proofs, optimistic period over),\n///      using attestation A to prove message inclusion on origin chain, whether the recipient reverted or not.\n/// ### Delivery tips.\n/// Paid to:\n///     - Executor who successfully executed the message on destination chain.\n///\n/// ## Tips encoding\n/// - Tips occupy a single storage word, and thus are stored on stack instead of being stored in memory.\n/// - The actual tip values should be determined by multiplying stored values by divided by TIPS_MULTIPLIER=2**32.\n/// - Tips are packed into a single word of storage, while allowing real values up to ~8*10**28 for every tip category.\n/// \u003e The only downside is that the \"real tip values\" are now multiplies of ~4*10**9, which should be fine even for\n/// the chains with the most expensive gas currency.\n/// # Tips stack layout (from highest bits to lowest)\n///\n/// | Position   | Field          | Type   | Bytes | Description                                                |\n/// | ---------- | -------------- | ------ | ----- | ---------------------------------------------------------- |\n/// | (032..024] | summitTip      | uint64 | 8     | Tip for agents interacting with Summit contract            |\n/// | (024..016] | attestationTip | uint64 | 8     | Tip for Notary posting attestation to Destination contract |\n/// | (016..008] | executionTip   | uint64 | 8     | Tip for valid execution attempt on destination chain       |\n/// | (008..000] | deliveryTip    | uint64 | 8     | Tip for successful message delivery on destination chain   |\n\nlibrary TipsLib {\n    using SafeCast for uint256;\n\n    /// @dev Amount of bits to shift to summitTip field\n    uint256 private constant SHIFT_SUMMIT_TIP = 24 * 8;\n    /// @dev Amount of bits to shift to attestationTip field\n    uint256 private constant SHIFT_ATTESTATION_TIP = 16 * 8;\n    /// @dev Amount of bits to shift to executionTip field\n    uint256 private constant SHIFT_EXECUTION_TIP = 8 * 8;\n\n    // ═══════════════════════════════════════════════════ TIPS ════════════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips with the given fields\n    /// @param summitTip_        Tip for agents interacting with Summit contract, divided by TIPS_MULTIPLIER\n    /// @param attestationTip_   Tip for Notary posting attestation to Destination contract, divided by TIPS_MULTIPLIER\n    /// @param executionTip_     Tip for valid execution attempt on destination chain, divided by TIPS_MULTIPLIER\n    /// @param deliveryTip_      Tip for successful message delivery on destination chain, divided by TIPS_MULTIPLIER\n    function encodeTips(uint64 summitTip_, uint64 attestationTip_, uint64 executionTip_, uint64 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // forgefmt: disable-next-item\n        return Tips.wrap(\n            uint256(summitTip_) \u003c\u003c SHIFT_SUMMIT_TIP |\n            uint256(attestationTip_) \u003c\u003c SHIFT_ATTESTATION_TIP |\n            uint256(executionTip_) \u003c\u003c SHIFT_EXECUTION_TIP |\n            uint256(deliveryTip_)\n        );\n    }\n\n    /// @notice Convenience function to encode tips with uint256 values.\n    function encodeTips256(uint256 summitTip_, uint256 attestationTip_, uint256 executionTip_, uint256 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // In practice, the tips amounts are not supposed to be higher than 2**96, and with 32 bits of granularity\n        // using uint64 is enough to store the values. However, we still check for overflow just in case.\n        // TODO: consider using Number type to store the tips values.\n        return encodeTips({\n            summitTip_: (summitTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            attestationTip_: (attestationTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            executionTip_: (executionTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            deliveryTip_: (deliveryTip_ \u003e\u003e TIPS_GRANULARITY).toUint64()\n        });\n    }\n\n    /// @notice Wraps the padded encoded tips into a Tips-typed value.\n    /// @dev There is no actual padding here, as the underlying type is already uint256,\n    /// but we include this function for consistency and to be future-proof, if tips will eventually use anything\n    /// smaller than uint256.\n    function wrapPadded(uint256 paddedTips) internal pure returns (Tips) {\n        return Tips.wrap(paddedTips);\n    }\n\n    /**\n     * @notice Returns a formatted Tips payload specifying empty tips.\n     * @return Formatted tips\n     */\n    function emptyTips() internal pure returns (Tips) {\n        return Tips.wrap(0);\n    }\n\n    /// @notice Returns tips's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Tips tips) internal pure returns (bytes32 hashedTips) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store tips in scratch space\n            mstore(0, tips)\n            // Compute hash of tips padded to 32 bytes\n            hashedTips := keccak256(0, 32)\n        }\n    }\n\n    // ═══════════════════════════════════════════════ TIPS SLICING ════════════════════════════════════════════════════\n\n    /// @notice Returns summitTip field\n    function summitTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_SUMMIT_TIP);\n    }\n\n    /// @notice Returns attestationTip field\n    function attestationTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_ATTESTATION_TIP);\n    }\n\n    /// @notice Returns executionTip field\n    function executionTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_EXECUTION_TIP);\n    }\n\n    /// @notice Returns deliveryTip field\n    function deliveryTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips));\n    }\n\n    // ════════════════════════════════════════════════ TIPS VALUE ═════════════════════════════════════════════════════\n\n    /// @notice Returns total value of the tips payload.\n    /// This is the sum of the encoded values, scaled up by TIPS_MULTIPLIER\n    function value(Tips tips) internal pure returns (uint256 value_) {\n        value_ = uint256(tips.summitTip()) + tips.attestationTip() + tips.executionTip() + tips.deliveryTip();\n        value_ \u003c\u003c= TIPS_GRANULARITY;\n    }\n\n    /// @notice Increases the delivery tip to match the new value.\n    function matchValue(Tips tips, uint256 newValue) internal pure returns (Tips newTips) {\n        uint256 oldValue = tips.value();\n        if (newValue \u003c oldValue) revert TipsValueTooLow();\n        // We want to increase the delivery tip, while keeping the other tips the same\n        unchecked {\n            uint256 delta = (newValue - oldValue) \u003e\u003e TIPS_GRANULARITY;\n            // `delta` fits into uint224, as TIPS_GRANULARITY is 32, so this never overflows uint256.\n            // In practice, this will never overflow uint64 as well, but we still check it just in case.\n            if (delta + tips.deliveryTip() \u003e type(uint64).max) revert TipsOverflow();\n            // Delivery tips occupy lowest 8 bytes, so we can just add delta to the tips value\n            // to effectively increase the delivery tip (knowing that delta fits into uint64).\n            newTips = Tips.wrap(Tips.unwrap(tips) + delta);\n        }\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    function __Ownable_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable_init_unchained() internal onlyInitializing {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n    function __Ownable2Step_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable2Step_init_unchained() internal onlyInitializing {\n    }\n    address private _pendingOwner;\n\n    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Returns the address of the pending owner.\n     */\n    function pendingOwner() public view virtual returns (address) {\n        return _pendingOwner;\n    }\n\n    /**\n     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual override onlyOwner {\n        _pendingOwner = newOwner;\n        emit OwnershipTransferStarted(owner(), newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual override {\n        delete _pendingOwner;\n        super._transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev The new owner accepts the ownership transfer.\n     */\n    function acceptOwnership() public virtual {\n        address sender = _msgSender();\n        require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n        _transferOwnership(sender);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// contracts/libs/memory/State.sol\n\n/// State is a memory view over a formatted state payload.\ntype State is uint256;\n\nusing StateLib for State global;\n\n/// # State\n/// State structure represents the state of Origin contract at some point of time.\n/// - State is structured in a way to track the updates of the Origin Merkle Tree.\n/// - State includes root of the Origin Merkle Tree, origin domain and some additional metadata.\n/// ## Origin Merkle Tree\n/// Hash of every sent message is inserted in the Origin Merkle Tree, which changes\n/// the value of Origin Merkle Root (which is the root for the mentioned tree).\n/// - Origin has a single Merkle Tree for all messages, regardless of their destination domain.\n/// - This leads to Origin state being updated if and only if a message was sent in a block.\n/// - Origin contract is a \"source of truth\" for states: a state is considered \"valid\" in its Origin,\n/// if it matches the state of the Origin contract after the N-th (nonce) message was sent.\n///\n/// # Memory layout of State fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                    |\n/// | ---------- | ----------- | ------- | ----- | ------------------------------ |\n/// | [000..032) | root        | bytes32 | 32    | Root of the Origin Merkle Tree |\n/// | [032..036) | origin      | uint32  | 4     | Domain where Origin is located |\n/// | [036..040) | nonce       | uint32  | 4     | Amount of sent messages        |\n/// | [040..045) | blockNumber | uint40  | 5     | Block of last sent message     |\n/// | [045..050) | timestamp   | uint40  | 5     | Time of last sent message      |\n/// | [050..062) | gasData     | uint96  | 12    | Gas data for the chain         |\n///\n/// @dev State could be used to form a Snapshot to be signed by a Guard or a Notary.\nlibrary StateLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_ROOT = 0;\n    uint256 private constant OFFSET_ORIGIN = 32;\n    uint256 private constant OFFSET_NONCE = 36;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 40;\n    uint256 private constant OFFSET_TIMESTAMP = 45;\n    uint256 private constant OFFSET_GAS_DATA = 50;\n\n    // ═══════════════════════════════════════════════════ STATE ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted State payload with provided fields\n     * @param root_         New merkle root\n     * @param origin_       Domain of Origin's chain\n     * @param nonce_        Nonce of the merkle root\n     * @param blockNumber_  Block number when root was saved in Origin\n     * @param timestamp_    Block timestamp when root was saved in Origin\n     * @param gasData_      Gas data for the chain\n     * @return Formatted state\n     */\n    function formatState(\n        bytes32 root_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_,\n        GasData gasData_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(root_, origin_, nonce_, blockNumber_, timestamp_, gasData_);\n    }\n\n    /**\n     * @notice Returns a State view over the given payload.\n     * @dev Will revert if the payload is not a state.\n     */\n    function castToState(bytes memory payload) internal pure returns (State) {\n        return castToState(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a State view.\n     * @dev Will revert if the memory view is not over a state.\n     */\n    function castToState(MemView memView) internal pure returns (State) {\n        if (!isState(memView)) revert UnformattedState();\n        return State.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted State.\n    function isState(MemView memView) internal pure returns (bool) {\n        return memView.len() == STATE_LENGTH;\n    }\n\n    /// @notice Returns the hash of a State, that could be later signed by a Guard to signal\n    /// that the state is invalid.\n    function hashInvalid(State state) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(stateInvalidSalt, keccak(state))\n        return state.unwrap().keccakSalted(STATE_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(State state) internal pure returns (MemView) {\n        return MemView.wrap(State.unwrap(state));\n    }\n\n    /// @notice Compares two State structures.\n    function equals(State a, State b) internal pure returns (bool) {\n        // Length of a State payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═══════════════════════════════════════════════ STATE HASHING ═══════════════════════════════════════════════════\n\n    /// @notice Returns the hash of the State.\n    /// @dev We are using the Merkle Root of a tree with two leafs (see below) as state hash.\n    function leaf(State state) internal pure returns (bytes32) {\n        (bytes32 leftLeaf_, bytes32 rightLeaf_) = state.subLeafs();\n        // Final hash is the parent of these leafs\n        return keccak256(bytes.concat(leftLeaf_, rightLeaf_));\n    }\n\n    /// @notice Returns \"sub-leafs\" of the State. Hash of these \"sub leafs\" is going to be used\n    /// as a \"state leaf\" in the \"Snapshot Merkle Tree\".\n    /// This enables proving that leftLeaf = (root, origin) was a part of the \"Snapshot Merkle Tree\",\n    /// by combining `rightLeaf` with the remainder of the \"Snapshot Merkle Proof\".\n    function subLeafs(State state) internal pure returns (bytes32 leftLeaf_, bytes32 rightLeaf_) {\n        MemView memView = state.unwrap();\n        // Left leaf is (root, origin)\n        leftLeaf_ = memView.prefix({len_: OFFSET_NONCE}).keccak();\n        // Right leaf is (metadata), or (nonce, blockNumber, timestamp)\n        rightLeaf_ = memView.sliceFrom({index_: OFFSET_NONCE}).keccak();\n    }\n\n    /// @notice Returns the left \"sub-leaf\" of the State.\n    function leftLeaf(bytes32 root_, uint32 origin_) internal pure returns (bytes32) {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(root_, origin_));\n    }\n\n    /// @notice Returns the right \"sub-leaf\" of the State.\n    function rightLeaf(uint32 nonce_, uint40 blockNumber_, uint40 timestamp_, GasData gasData_)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(nonce_, blockNumber_, timestamp_, gasData_));\n    }\n\n    // ═══════════════════════════════════════════════ STATE SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns a historical Merkle root from the Origin contract.\n    function root(State state) internal pure returns (bytes32) {\n        return state.unwrap().index({index_: OFFSET_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns domain of chain where the Origin contract is deployed.\n    function origin(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns nonce of Origin contract at the time, when `root` was the Merkle root.\n    function nonce(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when `root` was saved in Origin.\n    function blockNumber(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when `root` was saved in Origin.\n    /// @dev This is the timestamp according to the origin chain.\n    function timestamp(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n\n    /// @notice Returns gas data for the chain.\n    function gasData(State state) internal pure returns (GasData) {\n        return GasDataLib.wrapGasData(state.unwrap().indexUint({index_: OFFSET_GAS_DATA, bytes_: GAS_DATA_LENGTH}));\n    }\n}\n\n// contracts/libs/memory/BaseMessage.sol\n\n/// BaseMessage is a memory view over the base message supported by Origin-Destination\ntype BaseMessage is uint256;\n\nusing BaseMessageLib for BaseMessage global;\n\n/// BaseMessage structure represents a base message sent via the Origin-Destination contracts.\n/// - It only contains data relevant to the base message, the rest of data is encoded in the message header.\n/// - `sender` and `recipient` for EVM chains are EVM addresses casted to bytes32, while preserving left-alignment.\n/// - `tips` and `request` parameters are specified by a message sender\n/// \u003e Origin will calculate minimum tips for given request and content length, and will reject messages with tips\n/// lower than that.\n///\n/// # Memory layout of BaseMessage fields\n///\n/// | Position   | Field     | Type    | Bytes | Description                            |\n/// | ---------- | --------- | ------- | ----- | -------------------------------------- |\n/// | [000..032) | tips      | uint256 | 32    | Encoded tips paid on origin chain      |\n/// | [032..064) | sender    | bytes32 | 32    | Sender address on origin chain         |\n/// | [064..096) | recipient | bytes32 | 32    | Recipient address on destination chain |\n/// | [096..116) | request   | uint160 | 20    | Encoded request for message execution  |\n/// | [104..AAA) | content   | bytes   | ??    | Content to be passed to recipient      |\nlibrary BaseMessageLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_TIPS = 0;\n    uint256 private constant OFFSET_SENDER = 32;\n    uint256 private constant OFFSET_RECIPIENT = 64;\n    uint256 private constant OFFSET_REQUEST = OFFSET_RECIPIENT + TIPS_LENGTH;\n    uint256 private constant OFFSET_CONTENT = OFFSET_REQUEST + REQUEST_LENGTH;\n\n    // ═══════════════════════════════════════════════ BASE MESSAGE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted BaseMessage payload with provided fields.\n     * @param tips_         Encoded tips information\n     * @param sender_       Sender address on origin chain\n     * @param recipient_    Recipient address on destination chain\n     * @param request_      Encoded request for message execution\n     * @param content_      Raw content to be passed to recipient on destination chain\n     * @return Formatted base message\n     */\n    function formatBaseMessage(Tips tips_, bytes32 sender_, bytes32 recipient_, Request request_, bytes memory content_)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return abi.encodePacked(tips_, sender_, recipient_, request_, content_);\n    }\n\n    /**\n     * @notice Returns a BaseMessage view over the given payload.\n     * @dev Will revert if the payload is not a base message.\n     */\n    function castToBaseMessage(bytes memory payload) internal pure returns (BaseMessage) {\n        return castToBaseMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a BaseMessage view.\n     * @dev Will revert if the memory view is not over a base message payload.\n     */\n    function castToBaseMessage(MemView memView) internal pure returns (BaseMessage) {\n        if (!isBaseMessage(memView)) revert UnformattedBaseMessage();\n        return BaseMessage.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted BaseMessage.\n    function isBaseMessage(MemView memView) internal pure returns (bool) {\n        // Check if sender, recipient, tips fields exist\n        return (memView.len() \u003e= OFFSET_CONTENT);\n        // Content could be empty, so we don't check that\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(BaseMessage baseMessage) internal pure returns (MemView) {\n        return MemView.wrap(BaseMessage.unwrap(baseMessage));\n    }\n\n    /// @notice Returns baseMessage's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        // We hash \"tips\" and \"everything but tips\" to make tips proofs easier to verify\n        return MerkleMath.getParent(baseMessage.tips().leaf(), baseMessage.bodyLeaf());\n    }\n\n    /// @notice Returns hash for the \"everything but tips\" part of the base message.\n    function bodyLeaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_SENDER}).keccak();\n    }\n\n    // ═══════════════════════════════════════════ BASE MESSAGE SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips paid on origin chain.\n    function tips(BaseMessage baseMessage) internal pure returns (Tips) {\n        return TipsLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_TIPS, bytes_: TIPS_LENGTH})));\n    }\n\n    /// @notice Returns sender address on origin chain.\n    function sender(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_SENDER, bytes_: 32});\n    }\n\n    /// @notice Returns recipient address on destination chain.\n    function recipient(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_RECIPIENT, bytes_: 32});\n    }\n\n    /// @notice Returns an encoded request for message execution on destination chain.\n    function request(BaseMessage baseMessage) internal pure returns (Request) {\n        return RequestLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_REQUEST, bytes_: REQUEST_LENGTH})));\n    }\n\n    /// @notice Returns an untyped memory view over the content to be passed to recipient.\n    function content(BaseMessage baseMessage) internal pure returns (MemView) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_CONTENT});\n    }\n}\n\n// contracts/base/MessagingBase.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for all messaging contracts.\n * - Provides context on the local chain's domain.\n * - Provides ownership functionality.\n * - Will be providing pausing functionality when it is implemented.\n */\nabstract contract MessagingBase is MultiCallable, Versioned, Ownable2StepUpgradeable {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @notice Domain of the local chain, set once upon contract creation\n    uint32 public immutable localDomain;\n    // @notice Domain of the Synapse chain, set once upon contract creation\n    uint32 public immutable synapseDomain;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev gap for upgrade safety\n    uint256[50] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    constructor(string memory version_, uint32 synapseDomain_) Versioned(version_) {\n        localDomain = ChainContext.chainId();\n        synapseDomain = synapseDomain_;\n    }\n\n    // TODO: Implement pausing\n\n    /**\n     * @dev Should be impossible to renounce ownership;\n     * we override OpenZeppelin OwnableUpgradeable's\n     * implementation of renounceOwnership to make it a no-op\n     */\n    function renounceOwnership() public override onlyOwner {} //solhint-disable-line no-empty-blocks\n}\n\n// contracts/libs/memory/Message.sol\n\n/// Message is a memory over over a formatted message payload.\ntype Message is uint256;\n\nusing MessageLib for Message global;\n\n/// Library for formatting the various messages supported by Origin and Destination.\n///\n/// # Message memory layout\n///\n/// | Position   | Field  | Type    | Bytes | Description                                             |\n/// | ---------- | ------ | ------- | ----- | ------------------------------------------------------- |\n/// | [000..017) | header | uint136 | 17    | Encoded general routing information for the message     |\n/// | [017..AAA) | body   | bytes   | ??    | Formatted payload (according to flag) with message body |\nlibrary MessageLib {\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MemViewLib for bytes;\n    using HeaderLib for MemView;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_HEADER = 0;\n    uint256 private constant OFFSET_BODY = OFFSET_HEADER + HEADER_LENGTH;\n\n    // ══════════════════════════════════════════════════ MESSAGE ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns formatted message with provided fields.\n     * @param header_   Encoded general routing information for the message\n     * @param body_     Formatted payload (according to flag) with message body\n     * @return Formatted message\n     */\n    function formatMessage(Header header_, bytes memory body_) internal pure returns (bytes memory) {\n        return abi.encodePacked(header_, body_);\n    }\n\n    /**\n     * @notice Returns a Message view over for the given payload.\n     * @dev Will revert if the payload is not a message payload.\n     */\n    function castToMessage(bytes memory payload) internal pure returns (Message) {\n        return castToMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Message view.\n     * @dev Will revert if the memory view is not over a message payload.\n     */\n    function castToMessage(MemView memView) internal pure returns (Message) {\n        if (!isMessage(memView)) revert UnformattedMessage();\n        return Message.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Message.\n     */\n    function isMessage(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Check if headers exist in the payload\n        if (length \u003c OFFSET_BODY) return false;\n        // Check that Header is valid\n        uint256 paddedHeader = _header(memView);\n        if (!HeaderLib.isHeader(paddedHeader)) return false;\n        // Check that body is formatted according to the flag\n        // Only Base/Manager message flags exist\n        if (HeaderLib.wrapPadded(paddedHeader).flag() == MessageFlag.Base) {\n            // Check if body is a formatted base message\n            return _body(memView).isBaseMessage();\n        } else {\n            // Check if body is a formatted calldata for AgentManager call\n            return _body(memView).isCallData();\n        }\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Message message) internal pure returns (MemView) {\n        return MemView.wrap(Message.unwrap(message));\n    }\n\n    /// @notice Returns message's hash: a leaf to be inserted in the Merkle tree.\n    function leaf(Message message) internal pure returns (bytes32) {\n        // We hash header and body separately to make message proofs easier to verify\n        Header header_ = message.header();\n        // Only Base/Manager message flags exist\n        if (header_.flag() == MessageFlag.Base) {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToBaseMessage().leaf());\n        } else {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToCallData().leaf());\n        }\n    }\n\n    // ══════════════════════════════════════════════ MESSAGE SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns message's encoded header field.\n    function header(Message message) internal pure returns (Header) {\n        return HeaderLib.wrapPadded((message.unwrap().indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH})));\n    }\n\n    /// @notice Returns message's body field as an untyped memory view.\n    function body(Message message) internal pure returns (MemView) {\n        MemView memView = message.unwrap();\n        return _body(memView);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns message's padded header without checking that it is a valid header.\n    function _header(MemView memView) private pure returns (uint256) {\n        return memView.indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH});\n    }\n\n    /// @dev Returns an untyped memory view over the body field without checking\n    /// if the whole payload or the body are properly formatted.\n    function _body(MemView memView) private pure returns (MemView) {\n        return memView.sliceFrom({index_: OFFSET_BODY});\n    }\n}\n\n// contracts/base/AgentSecured.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for messaging contracts that are secured by the agent manager.\n * `AgentSecured` relies on `AgentManager` to provide the following functionality:\n * - Keep track of agents and their statuses.\n * - Pass agent-signed statements that were verified by the agent manager.\n * - These statements are considered valid indefinitely, unless the agent is disputed.\n * - Disputes are opened and resolved by the agent manager.\n * \u003e `AgentSecured` implementation should never use statements signed by agents that are disputed.\n */\nabstract contract AgentSecured is MessagingBase, IAgentSecured {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    address public immutable agentManager;\n\n    /// @inheritdoc IAgentSecured\n    address public immutable inbox;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    // (agent index =\u003e their dispute status: flag, openedAt, resolvedAt)\n    mapping(uint32 =\u003e DisputeStatus) internal _disputes;\n\n    /// @dev gap for upgrade safety\n    uint256[49] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    modifier onlyAgentManager() {\n        if (msg.sender != agentManager) revert CallerNotAgentManager();\n        _;\n    }\n\n    modifier onlyInbox() {\n        if (msg.sender != inbox) revert CallerNotInbox();\n        _;\n    }\n\n    constructor(string memory version_, uint32 synapseDomain_, address agentManager_, address inbox_)\n        MessagingBase(version_, synapseDomain_)\n    {\n        agentManager = agentManager_;\n        inbox = inbox_;\n    }\n\n    // ════════════════════════════════════════════ ONLY AGENT MANAGER ═════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external onlyAgentManager {\n        uint40 openedAt = ChainContext.blockTimestamp();\n        DisputeStatus memory status = DisputeStatus({flag: DisputeFlag.Pending, openedAt: openedAt, resolvedAt: 0});\n        _disputes[guardIndex] = status;\n        _disputes[notaryIndex] = status;\n    }\n\n    /// @inheritdoc IAgentSecured\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external onlyAgentManager {\n        // Update the dispute status of the slashed agent first.\n        uint40 resolvedAt = ChainContext.blockTimestamp();\n        _disputes[slashedIndex].flag = DisputeFlag.Slashed;\n        _disputes[slashedIndex].resolvedAt = resolvedAt;\n        // Mark the rival agent as not disputed, if there was an ongoing dispute.\n        if (rivalIndex != 0) {\n            _disputes[rivalIndex].flag = DisputeFlag.None;\n            _disputes[rivalIndex].resolvedAt = resolvedAt;\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function agentStatus(address agent) external view returns (AgentStatus memory) {\n        return _agentStatus(agent);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status) {\n        return _getAgent(index);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory) {\n        return _disputes[agentIndex];\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns status of the given agent: (flag, domain, index).\n    function _agentStatus(address agent) internal view returns (AgentStatus memory) {\n        return IAgentManager(agentManager).agentStatus(agent);\n    }\n\n    /// @dev Returns agent and their status for a given agent index. Returns zero values for non existing indexes.\n    function _getAgent(uint256 index) internal view returns (address agent, AgentStatus memory status) {\n        return IAgentManager(agentManager).getAgent(index);\n    }\n\n    /// @dev Checks if a Dispute exists for the given Notary. This function returns true, if\n    /// Notary is in ongoing Dispute, or if Dispute was resolved not in Notary's favor.\n    /// In both cases we can't trust Notary's data.\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeExists(uint32 notaryIndex) internal view returns (bool) {\n        return _disputes[notaryIndex].flag != DisputeFlag.None;\n    }\n\n    /// @dev Checks if a Notary recently won a Dispute and is still in the \"post-dispute\" timeout period.\n    /// In this period we still can't trust Notary's data, though we can optimistically assume that\n    /// that the data will be correct after the timeout (assuming no new Disputes are opened).\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeTimeout(uint32 notaryIndex) internal view returns (bool) {\n        DisputeStatus memory status = _disputes[notaryIndex];\n        // Exit early if Notary is in ongoing Dispute / slashed.\n        if (status.flag != DisputeFlag.None) return false;\n        // Check if Notary has been in any Dispute at all.\n        if (status.openedAt == 0) return false;\n        // Otherwise check if the Dispute timeout is still active.\n        return block.timestamp \u003c status.resolvedAt + DISPUTE_TIMEOUT_NOTARY;\n    }\n}\n\n// contracts/hubs/StateHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StateHub` is a parent contract for `Origin`. It is responsible for the following:\n/// - Keeping track of the historical Origin Merkle Tree containing all the message hashes.\n/// - Keeping track of the historical Origin States, as well as verifying their validity.\nabstract contract StateHub is AgentSecured, StateHubEvents, IStateHub {\n    using SafeCast for uint256;\n    using StateLib for bytes;\n\n    struct OriginState {\n        uint40 blockNumber;\n        uint40 timestamp;\n        GasData gasData;\n    }\n    // Bits left for tight packing: 80\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Historical Merkle Tree\n    /// Note: Takes two storage slots\n    HistoricalTree private _tree;\n\n    /// @dev All historical contract States\n    OriginState[] private _originStates;\n\n    /// @dev gap for upgrade safety\n    uint256[47] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IStateHub\n    function isValidState(bytes memory statePayload) external view returns (bool isValid) {\n        // This will revert if payload is not a formatted state\n        State state = statePayload.castToState();\n        return _isValidState(state);\n    }\n\n    /// @inheritdoc IStateHub\n    function statesAmount() external view returns (uint256) {\n        return _originStates.length;\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestLatestState() external view returns (bytes memory stateData) {\n        // This never underflows, assuming the contract was initialized\n        return suggestState(_nextNonce() - 1);\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestState(uint32 nonce) public view returns (bytes memory stateData) {\n        // This will revert if nonce is out of range\n        bytes32 root = _tree.root(nonce);\n        return _formatOriginState(_originStates[nonce], root, localDomain, nonce);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Initializes the saved states list by inserting a state for an empty Merkle Tree.\n    function _initializeStates() internal {\n        // This should only be called once, when the contract is initialized\n        // This will revert if _tree.roots is non-empty\n        bytes32 savedRoot = _tree.initializeRoots();\n        // Save root for empty merkle _tree with block number and timestamp of initialization\n        _saveState(savedRoot, _toOriginState());\n    }\n\n    /// @dev Inserts leaf into the Merkle Tree and saves the updated origin State.\n    function _insertAndSave(bytes32 leaf) internal {\n        bytes32 newRoot = _tree.insert(leaf);\n        _saveState(newRoot, _toOriginState());\n    }\n\n    /// @dev Saves an updated state of the Origin contract\n    function _saveState(bytes32 root, OriginState memory state) internal {\n        uint32 nonce = _nextNonce();\n        _originStates.push(state);\n        // Emit event with raw state data\n        emit StateSaved(_formatOriginState(state, root, localDomain, nonce));\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns nonce of the next sent message: the amount of saved States so far.\n    /// This always equals to \"total amount of sent messages\" plus 1.\n    function _nextNonce() internal view returns (uint32) {\n        // TODO: consider using more than 32 bits for origin nonces\n        return _originStates.length.toUint32();\n    }\n\n    /// @dev Checks if a state is valid, i.e. if it matches the historical one.\n    /// Reverts, if state refers to another Origin contract.\n    function _isValidState(State state) internal view returns (bool) {\n        // Check if state refers to this contract\n        if (state.origin() != localDomain) revert IncorrectOriginDomain();\n        // Check if nonce exists\n        uint32 nonce = state.nonce();\n        if (nonce \u003e= _originStates.length) return false;\n        // Check if state root matches the historical one\n        if (state.root() != _tree.root(nonce)) return false;\n        // Check if state metadata matches the historical one\n        return _areEqual(state, _originStates[nonce]);\n    }\n\n    // ═════════════════════════════════════════════ STRUCT FORMATTING ═════════════════════════════════════════════════\n\n    /// @dev Returns a formatted payload for a stored OriginState.\n    function _formatOriginState(OriginState memory originState, bytes32 root, uint32 origin, uint32 nonce)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return StateLib.formatState({\n            root_: root,\n            origin_: origin,\n            nonce_: nonce,\n            blockNumber_: originState.blockNumber,\n            timestamp_: originState.timestamp,\n            gasData_: originState.gasData\n        });\n    }\n\n    /// @dev Child contract should implement the logic for getting the current gas data from the gas oracle\n    /// to be saved as part of the Origin State.\n    // solhint-disable-next-line ordering\n    function _fetchGasData() internal view virtual returns (GasData);\n\n    /// @dev Returns a OriginState struct to save in the contract.\n    function _toOriginState() internal view returns (OriginState memory originState) {\n        originState.blockNumber = ChainContext.blockNumber();\n        originState.timestamp = ChainContext.blockTimestamp();\n        originState.gasData = _fetchGasData();\n    }\n\n    /// @dev Checks that a state and its Origin representation are equal.\n    function _areEqual(State state, OriginState memory originState) internal pure returns (bool) {\n        return state.blockNumber() == originState.blockNumber \u0026\u0026 state.timestamp() == originState.timestamp;\n    }\n}\n\n// contracts/Origin.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Origin` contract is used for sending messages to remote chains. It is done\n/// by inserting the message hashes into the Origin Merkle, which makes it possible to\n/// prove that message was sent using the Merkle proof against the Origin Merkle Root. This essentially\n/// compresses the list of messages into a single 32-byte value that needs to be stored on the destination chain.\n/// `Origin` is responsible for the following:\n/// - Formatting the sent message payloads, and inserting their hashes into the Origin Merkle Tree.\n/// - Keeping track of its own historical states (see parent contract `StateHub`).\n/// - Enforcing minimum tip values for sent base messages based on the provided execution requests.\n/// - Distributing the collected tips upon request from a local `AgentManager` contract.\ncontract Origin is StateHub, OriginEvents, InterfaceOrigin {\n    using MemViewLib for bytes;\n    using MessageLib for bytes;\n    using TipsLib for bytes;\n    using TypeCasts for address;\n\n    address public immutable gasOracle;\n\n    modifier onlyRemoteDestination(uint32 destination) {\n        if (destination == localDomain) revert IncorrectDestinationDomain();\n        _;\n    }\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_, address gasOracle_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {\n        gasOracle = gasOracle_;\n    }\n\n    /// @notice Initializes Origin contract:\n    /// - msg.sender is set as contract owner\n    /// - State of \"empty merkle tree\" is saved\n    function initialize() external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize \"states\": state of an \"empty merkle tree\" is saved\n        _initializeStates();\n    }\n\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable onlyRemoteDestination(destination) returns (uint32 messageNonce, bytes32 messageHash) {\n        // Check that content is not too large\n        if (content.length \u003e MAX_CONTENT_BYTES) revert ContentLengthTooBig();\n        // This will revert if msg.value is lower than value of minimum tips\n        Tips tips = _getMinimumTips(destination, paddedRequest, content.length).matchValue(msg.value);\n        Request request = RequestLib.wrapPadded(paddedRequest);\n        // Format the BaseMessage body\n        bytes memory body = BaseMessageLib.formatBaseMessage({\n            sender_: msg.sender.addressToBytes32(),\n            recipient_: recipient,\n            tips_: tips,\n            request_: request,\n            content_: content\n        });\n        // Send the message\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Base, body);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        onlyAgentManager\n        onlyRemoteDestination(destination)\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // AgentManager (checked via modifier) is responsible for constructing the calldata payload correctly.\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Manager, payload);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function withdrawTips(address recipient, uint256 amount) external onlyAgentManager {\n        if (address(this).balance \u003c amount) revert InsufficientEthBalance();\n        (bool success,) = recipient.call{value: amount}(\"\");\n        if (!success) revert EthTransferFailed();\n        emit TipWithdrawalCompleted(recipient, amount);\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue)\n    {\n        return _getMinimumTips(destination, paddedRequest, contentLength).value();\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Sends the given message to the specified destination. Message hash is inserted\n    /// into the Origin Merkle Tree, which will enable message execution on destination chain.\n    function _sendMessage(uint32 destination, uint32 optimisticPeriod, MessageFlag flag, bytes memory body)\n        internal\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // Format the message header\n        messageNonce = _nextNonce();\n        Header header = flag.encodeHeader({\n            origin_: localDomain,\n            nonce_: messageNonce,\n            destination_: destination,\n            optimisticPeriod_: optimisticPeriod\n        });\n        // Format the full message payload\n        bytes memory msgPayload = MessageLib.formatMessage(header, body);\n        // Insert new leaf into the Origin Merkle Tree and save the updated state\n        messageHash = msgPayload.castToMessage().leaf();\n        _insertAndSave(messageHash);\n        // Emit event with message information\n        emit Sent(messageHash, messageNonce, destination, msgPayload);\n        // Update the gas oracle data. We do this after the provided tips are checked so that\n        // the provided message is sent in the event that the gas oracle data is updated to a higher value.\n        InterfaceGasOracle(gasOracle).updateGasData(destination);\n        // TODO: consider doing this before the message is sent, while adjusting GasOracle.getMinimumTips() to\n        // use the pending gas oracle data.\n    }\n\n    /// @dev Returns the minimum tips for sending a message to the given destination with the given request and content.\n    function _getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        internal\n        view\n        returns (Tips)\n    {\n        return\n            TipsLib.wrapPadded(InterfaceGasOracle(gasOracle).getMinimumTips(destination, paddedRequest, contentLength));\n    }\n\n    /// @dev Gets the current gas data from the gas oracle to be saved as part of the Origin State.\n    function _fetchGasData() internal view override returns (GasData) {\n        return GasDataLib.wrapGasData(InterfaceGasOracle(gasOracle).getGasData());\n    }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"19685:4887:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;19685:4887:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"19685:4887:0:-:0;;;;;;;;","abiDefinition":[],"userDoc":{"kind":"user","methods":{},"notice":"# Number Library for compact representation of uint256 numbers. - Number is stored using mantissa and exponent, each occupying 8 bits. - Numbers under 2**8 are stored as `mantissa` with `exponent = 0xFF`. - Numbers at least 2**8 are approximated as `(256 + mantissa) \u003c\u003c exponent` \u003e - `0 \u003c= mantissa \u003c 256` \u003e - `0 \u003c= exponent \u003c= 247` (`256 * 2**248` doesn't fit into uint256) # Number stack layout (from highest bits to lowest) | Position   | Field    | Type  | Bytes | | ---------- | -------- | ----- | ----- | | (002..001] | mantissa | uint8 | 1     | | (001..000] | exponent | uint8 | 1     |","version":1},"developerDoc":{"kind":"dev","methods":{},"stateVariables":{"BWAD_SHIFT":{"details":"We are using not using 10**18 as wad, because it is not stored precisely in NumberLib."},"SHIFT_MANTISSA":{"details":"Amount of bits to shift to mantissa field"}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"stateVariables\":{\"BWAD_SHIFT\":{\"details\":\"We are using not using 10**18 as wad, because it is not stored precisely in NumberLib.\"},\"SHIFT_MANTISSA\":{\"details\":\"Amount of bits to shift to mantissa field\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"# Number Library for compact representation of uint256 numbers. - Number is stored using mantissa and exponent, each occupying 8 bits. - Numbers under 2**8 are stored as `mantissa` with `exponent = 0xFF`. - Numbers at least 2**8 are approximated as `(256 + mantissa) \u003c\u003c exponent` \u003e - `0 \u003c= mantissa \u003c 256` \u003e - `0 \u003c= exponent \u003c= 247` (`256 * 2**248` doesn't fit into uint256) # Number stack layout (from highest bits to lowest) | Position   | Field    | Type  | Bytes | | ---------- | -------- | ----- | ----- | | (002..001] | mantissa | uint8 | 1     | | (001..000] | exponent | uint8 | 1     |\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Origin.sol\":\"NumberLib\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Origin.sol\":{\"keccak256\":\"0x96775924f147f3d1f8df8cdf56731fe52a15af8d8e12e608efb8158c112b18cd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e642a27f5fab3c62b4c02e9754e9e42b1cf2e5381dbea9d3d106d23b7772ebe6\",\"dweb:/ipfs/QmUwn7ZyBvPkjnMuK8ZMSexBUdNQnVtxwyoAyT4DXLQjra\"]}},\"version\":1}"},"hashes":{}},"solidity/Origin.sol:Origin":{"code":"0x6101606040523480156200001257600080fd5b506040516200376138038062003761833981016040819052620000359162000164565b60408051808201909152600580825264302e302e3360d81b60208301526080528484848383816200006681620001cb565b60a081815250505062000083620000bc60201b620013941760201c565b63ffffffff90811660c0521660e052506001600160a01b0391821661010052811661012052929092166101405250620001f39350505050565b6000620000d446620000d960201b6200139b1760201c565b905090565b600063ffffffff821115620001435760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360448201526532206269747360d01b606482015260840160405180910390fd5b5090565b80516001600160a01b03811681146200015f57600080fd5b919050565b600080600080608085870312156200017b57600080fd5b845163ffffffff811681146200019057600080fd5b9350620001a06020860162000147565b9250620001b06040860162000147565b9150620001c06060860162000147565b905092959194509250565b80516020808301519190811015620001ed576000198160200360031b1b821691505b50919050565b60805160a05160c05160e0516101005161012051610140516134aa620002b7600039600081816102da0152818161162b01528181611a570152612357015260006105fd0152600081816103de01528181610691015281816109c001528181610e3a01528181610f2901528181611497015261154d0152600061039501526000818161046b01528181610d3401528181610e940152818161120d0152818161197401528181611aea01526120b4015260006102960152600061027301526134aa6000f3fe6080604052600436106101a15760003560e01c8063873661bd116100e1578063b4596b4b1161008a578063e30c397811610064578063e30c39781461058a578063f2437942146105b5578063f2fde38b146105cb578063fb0e722b146105eb57600080fd5b8063b4596b4b14610528578063c0b56f7c14610548578063dfadd81a1461055d57600080fd5b8063a1c702a7116100bb578063a1c702a7146104b8578063a2155c34146104d8578063a9dcf22d146104f857600080fd5b8063873661bd1461042a5780638d3638f4146104595780638da5cb5b1461048d57600080fd5b806360fc84661161014e578063717b863811610128578063717b8638146103835780637622f78d146103cc57806379ba5097146104005780638129fc1c1461041557600080fd5b806360fc846614610321578063611692181461034e578063715018a61461036e57600080fd5b80634fc6ad851161017f5780634fc6ad851461022c57806354fd4d501461025a5780635d62a8dd146102c857600080fd5b806328f3fac9146101a65780632de5aaf7146101dc5780634e04e7a71461020a575b600080fd5b3480156101b257600080fd5b506101c66101c1366004612ade565b61061f565b6040516101d39190612b5f565b60405180910390f35b3480156101e857600080fd5b506101fc6101f7366004612b6d565b61064b565b6040516101d3929190612b86565b34801561021657600080fd5b5061022a610225366004612bb0565b610679565b005b34801561023857600080fd5b5061024c610247366004612bee565b610811565b6040519081526020016101d3565b34801561026657600080fd5b50604080518082019091527f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201525b6040516101d39190612c91565b3480156102d457600080fd5b506102fc7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101d3565b34801561032d57600080fd5b5061034161033c366004612ca4565b610830565b6040516101d39190612d19565b34801561035a57600080fd5b5061022a610369366004612dad565b6109a8565b34801561037a57600080fd5b5061022a610ad1565b34801561038f57600080fd5b506103b77f000000000000000000000000000000000000000000000000000000000000000081565b60405163ffffffff90911681526020016101d3565b3480156103d857600080fd5b506102fc7f000000000000000000000000000000000000000000000000000000000000000081565b34801561040c57600080fd5b5061022a610adb565b34801561042157600080fd5b5061022a610b95565b61043d610438366004612ec0565b610d2e565b6040805163ffffffff90931683526020830191909152016101d3565b34801561046557600080fd5b506103b77f000000000000000000000000000000000000000000000000000000000000000081565b34801561049957600080fd5b5060335473ffffffffffffffffffffffffffffffffffffffff166102fc565b3480156104c457600080fd5b5061043d6104d3366004612f36565b610e1f565b3480156104e457600080fd5b5061022a6104f3366004612dad565b610f11565b34801561050457600080fd5b50610518610513366004612f98565b611162565b60405190151581526020016101d3565b34801561053457600080fd5b506102bb610543366004612fcd565b611179565b34801561055457600080fd5b506102bb611232565b34801561056957600080fd5b5061057d610578366004612fcd565b611250565b6040516101d39190612fea565b34801561059657600080fd5b5060655473ffffffffffffffffffffffffffffffffffffffff166102fc565b3480156105c157600080fd5b5061011c5461024c565b3480156105d757600080fd5b5061022a6105e6366004612ade565b6112e4565b3480156105f757600080fd5b506102fc7f000000000000000000000000000000000000000000000000000000000000000081565b604080516060810182526000808252602082018190529181019190915261064582611435565b92915050565b6040805160608101825260008082526020820181905291810182905261067083611502565b91509150915091565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146106e8576040517ff79626c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80471015610722576040517fb6d6e7d600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d806000811461077c576040519150601f19603f3d011682016040523d82523d6000602084013e610781565b606091505b50509050806107bc576040517f6d963f8800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff85168152602081018490527fdd7931769f40354ba0d22c17b3d6b6a95ef7d06d9d0f4c1a637c4b639fcb8c2291015b60405180910390a1505050565b60006108266108218585856115cd565b611699565b90505b9392505050565b6060818067ffffffffffffffff81111561084c5761084c612de6565b60405190808252806020026020018201604052801561089257816020015b60408051808201909152600081526060602082015281526020019060019003908161086a5790505b5091503660005b8281101561099f578585828181106108b3576108b361302c565b90506020028101906108c5919061305b565b915060008482815181106108db576108db61302c565b602002602001015190503073ffffffffffffffffffffffffffffffffffffffff1683806020019061090c9190613099565b60405161091a929190613105565b600060405180830381855af49150503d8060008114610955576040519150601f19603f3d011682016040523d82523d6000602084013e61095a565b606091505b5060208301521515808252833517610996577f4d6a23280000000000000000000000000000000000000000000000000000000060005260046000fd5b50600101610899565b50505092915050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610a17576040517ff79626c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610a21611709565b63ffffffff848116600090815260c960205260409020805464ffffffffff84166601000000000000027fffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffff00909116176002179055909150821615610acc5763ffffffff8216600090815260c96020526040902080547fffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffff0016660100000000000064ffffffffff8416021790555b505050565b610ad9611714565b565b606554339073ffffffffffffffffffffffffffffffffffffffff168114610b89576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e6572000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b610b9281611795565b50565b600054610100900460ff1615808015610bb55750600054600160ff909116105b80610bcf5750303b158015610bcf575060005460ff166001145b610c5b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610b80565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610cb957600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610cc16117c6565b610cc9611865565b8015610b9257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150565b600080867f000000000000000000000000000000000000000000000000000000000000000063ffffffff168163ffffffff1603610d97576040517fa752c23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61080084511115610dd4576040517fb974c30200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610dec34610de68b8989516115cd565b90611884565b9050856000610dfe83338c858b61192b565b9050610e0d8b8a600084611960565b95509550505050509550959350505050565b6000803373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610e91576040517ff79626c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b847f000000000000000000000000000000000000000000000000000000000000000063ffffffff168163ffffffff1603610ef7576040517fa752c23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f048686600187611960565b9250925050935093915050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610f80576040517ff79626c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610f8a611709565b90506000604051806060016040528060016002811115610fac57610fac612afb565b815264ffffffffff84166020808301919091526000604092830181905263ffffffff8816815260c99091522081518154929350839282907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600183600281111561101957611019612afb565b0217905550602082810151825460409485015164ffffffffff9081166601000000000000027fffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffffff9190931661010002167fffffffffffffffffffffffffffffffffffffffffff00000000000000000000ff909116171790915563ffffffff8516600090815260c990915220815181548392919082907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660018360028111156110e3576110e3612afb565b0217905550602082015181546040909301517fffffffffffffffffffffffffffffffffffffffffff00000000000000000000ff90931661010064ffffffffff928316027fffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffffff16176601000000000000919093160291909117905550505050565b60008061116e83611ad3565b905061082981611ae6565b6060600061119160fb63ffffffff80861690611c2416565b905061082961011c8463ffffffff16815481106111b0576111b061302c565b600091825260209182902060408051606081018252919092015464ffffffffff808216835265010000000000820416938201939093526bffffffffffffffffffffffff6a01000000000000000000009093049290921690820152827f000000000000000000000000000000000000000000000000000000000000000086611c8c565b606061124b6001611241611d65565b6105439190613144565b905090565b604080516060810182526000808252602082018190529181019190915263ffffffff8216600090815260c96020526040908190208151606081019092528054829060ff1660028111156112a5576112a5612afb565b60028111156112b6576112b6612afb565b8152905464ffffffffff61010082048116602084015266010000000000009091041660409091015292915050565b6112ec611714565b6065805473ffffffffffffffffffffffffffffffffffffffff83167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116811790915561134f60335473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b600061124b465b600063ffffffff821115611431576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360448201527f32206269747300000000000000000000000000000000000000000000000000006064820152608401610b80565b5090565b60408051606081018252600080825260208201819052918101919091526040517f28f3fac900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301527f000000000000000000000000000000000000000000000000000000000000000016906328f3fac990602401606060405180830381865afa1580156114de573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064591906131dd565b604080516060810182526000808252602082018190529181018290526040517f2de5aaf7000000000000000000000000000000000000000000000000000000008152600481018490527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632de5aaf790602401608060405180830381865afa1580156115a9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061067091906131f9565b6040517f72010a9300000000000000000000000000000000000000000000000000000000815263ffffffff8416600482015260248101839052604481018290526000906108269073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906372010a9390606401602060405180830381865afa158015611672573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611696919061322f565b90565b60008167ffffffffffffffff166116b08360401c90565b67ffffffffffffffff166116c48460801c90565b67ffffffffffffffff166116d88560c01c90565b67ffffffffffffffff166116ec9190613248565b6116f69190613248565b6117009190613248565b60201b92915050565b600061124b42611d75565b60335473ffffffffffffffffffffffffffffffffffffffff163314610ad9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b80565b606580547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055610b9281611e0c565b600054610100900460ff1661185d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610b80565b610ad9611e83565b600061187160fb611f23565b9050610b928161187f611f56565b611fb6565b60008061189084611699565b9050808310156118cc576040517f429726c100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80830360201c67ffffffffffffffff8567ffffffffffffffff1682011115611920576040517f1b438b3300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b939093019392505050565b6060858585858560405160200161194695949392919061325b565b604051602081830303815290604052905095945050505050565b60008061196b611d65565b915060006119b17f00000000000000000000000000000000000000000000000000000000000000008489898960018111156119a8576119a8612afb565b939291906120e6565b905060006119bf828661214f565b90506119d26119cd8261217b565b61218e565b92506119dd83612253565b8763ffffffff168463ffffffff16847fcb1f6736605c149e8d69fd9f5393ff113515c28fa5848a3dc26dbde76dd16e8784604051611a1b9190612c91565b60405180910390a46040517f867baea500000000000000000000000000000000000000000000000000000000815263ffffffff891660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063867baea590602401600060405180830381600087803b158015611ab057600080fd5b505af1158015611ac4573d6000803e3d6000fd5b50505050505094509492505050565b6000610645611ae183612272565b61228d565b60007f000000000000000000000000000000000000000000000000000000000000000063ffffffff16611b18836122ce565b63ffffffff1614611b55576040517f3eeb1dd400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611b60836122e0565b61011c5490915063ffffffff821610611b7c5750600092915050565b611b9060fb63ffffffff80841690611c2416565b611b99846122ef565b14611ba75750600092915050565b6108298361011c8363ffffffff1681548110611bc557611bc561302c565b600091825260209182902060408051606081018252919092015464ffffffffff808216835265010000000000820416938201939093526bffffffffffffffffffffffff6a010000000000000000000090930492909216908201526122fd565b60208201546000908210611c64576040517f8397c2ad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826020018281548110611c7957611c7961302c565b9060005260206000200154905092915050565b6060611d5c848484886000015189602001518a6040015160408051602081019790975260e095861b7fffffffff00000000000000000000000000000000000000000000000000000000908116888301529490951b909316604486015260d891821b7fffffffffff0000000000000000000000000000000000000000000000000000009081166048870152911b16604d84015260a01b7fffffffffffffffffffffffff00000000000000000000000000000000000000001660528301528051603e818403018152605e909201905290565b95945050505050565b61011c5460009061124b9061139b565b600064ffffffffff821115611431576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203460448201527f30206269747300000000000000000000000000000000000000000000000000006064820152608401610b80565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16611f1a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610b80565b610ad933611795565b602081015460009015611f3857611f386132bb565b60209182018054600181018255600091825292902090910181905590565b6040805160608101825260008082526020820181905291810191909152611f7b612345565b64ffffffffff168152611f8c611709565b64ffffffffff166020820152611fa0612350565b6bffffffffffffffffffffffff16604082015290565b6000611fc0611d65565b61011c805460018101825560009190915283517fadd86a4592312086270d45a94ec1626035e36f7028a1706ab88a5151613929fe9091018054602086015160408701516bffffffffffffffffffffffff166a0100000000000000000000027fffffffffffffffffffff000000000000000000000000ffffffffffffffffffff64ffffffffff92831665010000000000027fffffffffffffffffffffffffffffffffffffffffffff000000000000000000009094169290951691909117919091179290921691909117905590507fc82fd59396134ccdeb4ce594571af6fe8f87d1df40fb6aaf1463ee06d610d0cb6120d983857f000000000000000000000000000000000000000000000000000000000000000085611c8c565b6040516108049190612c91565b600063ffffffff821667ffffffff00000000602085901b166bffffffff0000000000000000604087901b166fffffffff000000000000000000000000606089901b1660808a600181111561213c5761213c612afb565b60ff16901b171717179695505050505050565b606082826040516020016121649291906132ea565b604051602081830303815290604052905092915050565b600061064561218983612272565b6123c0565b60008061219a83612401565b905060006121ba8270ffffffffffffffffffffffffffffffffff16612417565b60018111156121cb576121cb612afb565b03612214576108296121f68270ffffffffffffffffffffffffffffffffff1660009081526020902090565b61220f61220a6122058761244a565b612456565b612497565b6124bd565b61082961223a8270ffffffffffffffffffffffffffffffffff1660009081526020902090565b61220f61224e6122498761244a565b612509565b61254a565b600061226060fb8361255a565b905061226e8161187f611f56565b5050565b805160009060208301612285818361259a565b949350505050565b6000612298826125fd565b611431576040517f6ba041c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061064560206004845b9190612625565b600061064560246004846122d9565b600061064582826020612646565b805160009064ffffffffff1661231284612750565b64ffffffffff161480156108295750816020015164ffffffffff166123368461275f565b64ffffffffff16149392505050565b600061124b43611d75565b600061124b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166334926b296040518163ffffffff1660e01b8152600401602060405180830381865afa158015611672573d6000803e3d6000fd5b60006123cb8261276e565b611431576040517fd082b2a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610645612412826011856122d9565b612823565b60006124368270ffffffffffffffffffffffffffffffffff1660801c90565b60ff16600181111561064557610645612afb565b60008161082981612867565b60006124618261287e565b611431576040517f35c196ef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006106456124b46124a8846128b3565b60009081526020902090565b61220f846128c4565b6000821580156124cb575081155b156124d857506000610645565b6040805160208101859052908101839052606001604051602081830303815290604052805190602001209050610645565b6000612514826128d4565b611431576040517f9d46362800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061064582612910565b612910565b602082015460009061256d84828561293b565b61257784826129f3565b602094850180546001810182556000918252959020909401849055509192915050565b6000806125a78385613248565b90506040518111156125b7575060005b806000036125f1576040517f10bef38600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b608084901b8317612285565b600061260b600c6032613248565b6fffffffffffffffffffffffffffffffff83161492915050565b600080612633858585612646565b602084900360031b1c9150509392505050565b60008160000361265857506000610829565b6020821115612693576040517f31d784a800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6fffffffffffffffffffffffffffffffff84166126b08385613248565b11156126e8576040517fa3b99ded00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600382901b60006126f98660801c90565b909401517f80000000000000000000000000000000000000000000000000000000000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092019190911d16949350505050565b600061064560286005846122d9565b6000610645602d6005846122d9565b60006fffffffffffffffffffffffffffffffff821661278e601183613248565b81101561279e5750600092915050565b60006127a984612a48565b9050600160ff608083901c1611156127c5575060009392505050565b60006127eb6127d383612823565b70ffffffffffffffffffffffffffffffffff16612417565b60018111156127fc576127fc612afb565b036128125761228561280d85612867565b61287e565b61228561281e85612867565b6128d4565b6000600160ff608084901c161115611431576040517f58ebbfbe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610645612877601183613248565b8390612a56565b6000601861288e60206040613248565b6128989190613248565b6fffffffffffffffffffffffffffffffff8316101592915050565b6000610645611696826020856122d9565b6000610645612555836020612a56565b60006fffffffffffffffffffffffffffffffff821660048110156128fb5750600092915050565b610829612909600483613335565b601f161590565b60008061291d8360801c90565b6fffffffffffffffffffffffffffffffff9390931690922092915050565b600161294960206002613468565b6129539190613335565b82111561298c576040517fef5ccf6600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b60208110156129ea57826001166001036129be57818482602081106129b6576129b661302c565b015550505050565b6129db8482602081106129d3576129d361302c565b0154836124bd565b600193841c939092500161298f565b50610acc6132bb565b6000805b6020811015612a415782600116600103612a2757612a208482602081106129d3576129d361302c565b9150612a35565b612a328260006124bd565b91505b600192831c92016129f7565b5092915050565b600061064582826011612625565b60006fffffffffffffffffffffffffffffffff831680831115612aa5576040517fa3b99ded00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61228583612ab38660801c90565b0184830361259a565b73ffffffffffffffffffffffffffffffffffffffff81168114610b9257600080fd5b600060208284031215612af057600080fd5b813561082981612abc565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b805160068110612b3c57612b3c612afb565b825260208181015163ffffffff9081169184019190915260409182015116910152565b606081016106458284612b2a565b600060208284031215612b7f57600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff83168152608081016108296020830184612b2a565b60008060408385031215612bc357600080fd5b8235612bce81612abc565b946020939093013593505050565b63ffffffff81168114610b9257600080fd5b600080600060608486031215612c0357600080fd5b8335612c0e81612bdc565b95602085013595506040909401359392505050565b60005b83811015612c3e578181015183820152602001612c26565b50506000910152565b60008151808452612c5f816020860160208601612c23565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006108296020830184612c47565b60008060208385031215612cb757600080fd5b823567ffffffffffffffff80821115612ccf57600080fd5b818501915085601f830112612ce357600080fd5b813581811115612cf257600080fd5b8660208260051b8501011115612d0757600080fd5b60209290920196919550909350505050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b83811015612d9f578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00185528151805115158452870151878401879052612d8c87850182612c47565b9588019593505090860190600101612d40565b509098975050505050505050565b60008060408385031215612dc057600080fd5b8235612dcb81612bdc565b91506020830135612ddb81612bdc565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f830112612e2657600080fd5b813567ffffffffffffffff80821115612e4157612e41612de6565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715612e8757612e87612de6565b81604052838152866020858801011115612ea057600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600080600060a08688031215612ed857600080fd5b8535612ee381612bdc565b9450602086013593506040860135612efa81612bdc565b925060608601359150608086013567ffffffffffffffff811115612f1d57600080fd5b612f2988828901612e15565b9150509295509295909350565b600080600060608486031215612f4b57600080fd5b8335612f5681612bdc565b92506020840135612f6681612bdc565b9150604084013567ffffffffffffffff811115612f8257600080fd5b612f8e86828701612e15565b9150509250925092565b600060208284031215612faa57600080fd5b813567ffffffffffffffff811115612fc157600080fd5b61228584828501612e15565b600060208284031215612fdf57600080fd5b813561082981612bdc565b815160608201906003811061300157613001612afb565b80835250602083015164ffffffffff8082166020850152806040860151166040850152505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc183360301811261308f57600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126130ce57600080fd5b83018035915067ffffffffffffffff8211156130e957600080fd5b6020019150368190038213156130fe57600080fd5b9250929050565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b63ffffffff828116828216039080821115612a4157612a41613115565b60006060828403121561317357600080fd5b6040516060810181811067ffffffffffffffff8211171561319657613196612de6565b80604052508091508251600681106131ad57600080fd5b815260208301516131bd81612bdc565b602082015260408301516131d081612bdc565b6040919091015292915050565b6000606082840312156131ef57600080fd5b6108298383613161565b6000806080838503121561320c57600080fd5b825161321781612abc565b91506132268460208501613161565b90509250929050565b60006020828403121561324157600080fd5b5051919050565b8082018082111561064557610645613115565b8581528460208201528360408201527fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000008360401b166060820152600082516132aa816078850160208701612c23565b919091016078019695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b7fffffffffffffffffffffffffffffffffff0000000000000000000000000000008360781b16815260008251613327816011850160208701612c23565b919091016011019392505050565b8181038181111561064557610645613115565b600181815b808511156133a157817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561338757613387613115565b8085161561339457918102915b93841c939080029061334d565b509250929050565b6000826133b857506001610645565b816133c557506000610645565b81600181146133db57600281146133e557613401565b6001915050610645565b60ff8411156133f6576133f6613115565b50506001821b610645565b5060208310610133831016604e8410600b8410161715613424575081810a610645565b61342e8383613348565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561346057613460613115565b029392505050565b600061082983836133a956fea26469706673582212209ab634ffccdc2b40f674be443c69bf400699022767c9d83cb887cc64e0b62cdb64736f6c63430008110033","runtime-code":"0x6080604052600436106101a15760003560e01c8063873661bd116100e1578063b4596b4b1161008a578063e30c397811610064578063e30c39781461058a578063f2437942146105b5578063f2fde38b146105cb578063fb0e722b146105eb57600080fd5b8063b4596b4b14610528578063c0b56f7c14610548578063dfadd81a1461055d57600080fd5b8063a1c702a7116100bb578063a1c702a7146104b8578063a2155c34146104d8578063a9dcf22d146104f857600080fd5b8063873661bd1461042a5780638d3638f4146104595780638da5cb5b1461048d57600080fd5b806360fc84661161014e578063717b863811610128578063717b8638146103835780637622f78d146103cc57806379ba5097146104005780638129fc1c1461041557600080fd5b806360fc846614610321578063611692181461034e578063715018a61461036e57600080fd5b80634fc6ad851161017f5780634fc6ad851461022c57806354fd4d501461025a5780635d62a8dd146102c857600080fd5b806328f3fac9146101a65780632de5aaf7146101dc5780634e04e7a71461020a575b600080fd5b3480156101b257600080fd5b506101c66101c1366004612ade565b61061f565b6040516101d39190612b5f565b60405180910390f35b3480156101e857600080fd5b506101fc6101f7366004612b6d565b61064b565b6040516101d3929190612b86565b34801561021657600080fd5b5061022a610225366004612bb0565b610679565b005b34801561023857600080fd5b5061024c610247366004612bee565b610811565b6040519081526020016101d3565b34801561026657600080fd5b50604080518082019091527f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201525b6040516101d39190612c91565b3480156102d457600080fd5b506102fc7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101d3565b34801561032d57600080fd5b5061034161033c366004612ca4565b610830565b6040516101d39190612d19565b34801561035a57600080fd5b5061022a610369366004612dad565b6109a8565b34801561037a57600080fd5b5061022a610ad1565b34801561038f57600080fd5b506103b77f000000000000000000000000000000000000000000000000000000000000000081565b60405163ffffffff90911681526020016101d3565b3480156103d857600080fd5b506102fc7f000000000000000000000000000000000000000000000000000000000000000081565b34801561040c57600080fd5b5061022a610adb565b34801561042157600080fd5b5061022a610b95565b61043d610438366004612ec0565b610d2e565b6040805163ffffffff90931683526020830191909152016101d3565b34801561046557600080fd5b506103b77f000000000000000000000000000000000000000000000000000000000000000081565b34801561049957600080fd5b5060335473ffffffffffffffffffffffffffffffffffffffff166102fc565b3480156104c457600080fd5b5061043d6104d3366004612f36565b610e1f565b3480156104e457600080fd5b5061022a6104f3366004612dad565b610f11565b34801561050457600080fd5b50610518610513366004612f98565b611162565b60405190151581526020016101d3565b34801561053457600080fd5b506102bb610543366004612fcd565b611179565b34801561055457600080fd5b506102bb611232565b34801561056957600080fd5b5061057d610578366004612fcd565b611250565b6040516101d39190612fea565b34801561059657600080fd5b5060655473ffffffffffffffffffffffffffffffffffffffff166102fc565b3480156105c157600080fd5b5061011c5461024c565b3480156105d757600080fd5b5061022a6105e6366004612ade565b6112e4565b3480156105f757600080fd5b506102fc7f000000000000000000000000000000000000000000000000000000000000000081565b604080516060810182526000808252602082018190529181019190915261064582611435565b92915050565b6040805160608101825260008082526020820181905291810182905261067083611502565b91509150915091565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146106e8576040517ff79626c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80471015610722576040517fb6d6e7d600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d806000811461077c576040519150601f19603f3d011682016040523d82523d6000602084013e610781565b606091505b50509050806107bc576040517f6d963f8800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff85168152602081018490527fdd7931769f40354ba0d22c17b3d6b6a95ef7d06d9d0f4c1a637c4b639fcb8c2291015b60405180910390a1505050565b60006108266108218585856115cd565b611699565b90505b9392505050565b6060818067ffffffffffffffff81111561084c5761084c612de6565b60405190808252806020026020018201604052801561089257816020015b60408051808201909152600081526060602082015281526020019060019003908161086a5790505b5091503660005b8281101561099f578585828181106108b3576108b361302c565b90506020028101906108c5919061305b565b915060008482815181106108db576108db61302c565b602002602001015190503073ffffffffffffffffffffffffffffffffffffffff1683806020019061090c9190613099565b60405161091a929190613105565b600060405180830381855af49150503d8060008114610955576040519150601f19603f3d011682016040523d82523d6000602084013e61095a565b606091505b5060208301521515808252833517610996577f4d6a23280000000000000000000000000000000000000000000000000000000060005260046000fd5b50600101610899565b50505092915050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610a17576040517ff79626c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610a21611709565b63ffffffff848116600090815260c960205260409020805464ffffffffff84166601000000000000027fffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffff00909116176002179055909150821615610acc5763ffffffff8216600090815260c96020526040902080547fffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffff0016660100000000000064ffffffffff8416021790555b505050565b610ad9611714565b565b606554339073ffffffffffffffffffffffffffffffffffffffff168114610b89576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e6572000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b610b9281611795565b50565b600054610100900460ff1615808015610bb55750600054600160ff909116105b80610bcf5750303b158015610bcf575060005460ff166001145b610c5b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610b80565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610cb957600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610cc16117c6565b610cc9611865565b8015610b9257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150565b600080867f000000000000000000000000000000000000000000000000000000000000000063ffffffff168163ffffffff1603610d97576040517fa752c23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61080084511115610dd4576040517fb974c30200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610dec34610de68b8989516115cd565b90611884565b9050856000610dfe83338c858b61192b565b9050610e0d8b8a600084611960565b95509550505050509550959350505050565b6000803373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610e91576040517ff79626c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b847f000000000000000000000000000000000000000000000000000000000000000063ffffffff168163ffffffff1603610ef7576040517fa752c23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f048686600187611960565b9250925050935093915050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610f80576040517ff79626c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610f8a611709565b90506000604051806060016040528060016002811115610fac57610fac612afb565b815264ffffffffff84166020808301919091526000604092830181905263ffffffff8816815260c99091522081518154929350839282907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600183600281111561101957611019612afb565b0217905550602082810151825460409485015164ffffffffff9081166601000000000000027fffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffffff9190931661010002167fffffffffffffffffffffffffffffffffffffffffff00000000000000000000ff909116171790915563ffffffff8516600090815260c990915220815181548392919082907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660018360028111156110e3576110e3612afb565b0217905550602082015181546040909301517fffffffffffffffffffffffffffffffffffffffffff00000000000000000000ff90931661010064ffffffffff928316027fffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffffff16176601000000000000919093160291909117905550505050565b60008061116e83611ad3565b905061082981611ae6565b6060600061119160fb63ffffffff80861690611c2416565b905061082961011c8463ffffffff16815481106111b0576111b061302c565b600091825260209182902060408051606081018252919092015464ffffffffff808216835265010000000000820416938201939093526bffffffffffffffffffffffff6a01000000000000000000009093049290921690820152827f000000000000000000000000000000000000000000000000000000000000000086611c8c565b606061124b6001611241611d65565b6105439190613144565b905090565b604080516060810182526000808252602082018190529181019190915263ffffffff8216600090815260c96020526040908190208151606081019092528054829060ff1660028111156112a5576112a5612afb565b60028111156112b6576112b6612afb565b8152905464ffffffffff61010082048116602084015266010000000000009091041660409091015292915050565b6112ec611714565b6065805473ffffffffffffffffffffffffffffffffffffffff83167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116811790915561134f60335473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b600061124b465b600063ffffffff821115611431576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360448201527f32206269747300000000000000000000000000000000000000000000000000006064820152608401610b80565b5090565b60408051606081018252600080825260208201819052918101919091526040517f28f3fac900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301527f000000000000000000000000000000000000000000000000000000000000000016906328f3fac990602401606060405180830381865afa1580156114de573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064591906131dd565b604080516060810182526000808252602082018190529181018290526040517f2de5aaf7000000000000000000000000000000000000000000000000000000008152600481018490527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632de5aaf790602401608060405180830381865afa1580156115a9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061067091906131f9565b6040517f72010a9300000000000000000000000000000000000000000000000000000000815263ffffffff8416600482015260248101839052604481018290526000906108269073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906372010a9390606401602060405180830381865afa158015611672573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611696919061322f565b90565b60008167ffffffffffffffff166116b08360401c90565b67ffffffffffffffff166116c48460801c90565b67ffffffffffffffff166116d88560c01c90565b67ffffffffffffffff166116ec9190613248565b6116f69190613248565b6117009190613248565b60201b92915050565b600061124b42611d75565b60335473ffffffffffffffffffffffffffffffffffffffff163314610ad9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b80565b606580547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055610b9281611e0c565b600054610100900460ff1661185d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610b80565b610ad9611e83565b600061187160fb611f23565b9050610b928161187f611f56565b611fb6565b60008061189084611699565b9050808310156118cc576040517f429726c100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80830360201c67ffffffffffffffff8567ffffffffffffffff1682011115611920576040517f1b438b3300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b939093019392505050565b6060858585858560405160200161194695949392919061325b565b604051602081830303815290604052905095945050505050565b60008061196b611d65565b915060006119b17f00000000000000000000000000000000000000000000000000000000000000008489898960018111156119a8576119a8612afb565b939291906120e6565b905060006119bf828661214f565b90506119d26119cd8261217b565b61218e565b92506119dd83612253565b8763ffffffff168463ffffffff16847fcb1f6736605c149e8d69fd9f5393ff113515c28fa5848a3dc26dbde76dd16e8784604051611a1b9190612c91565b60405180910390a46040517f867baea500000000000000000000000000000000000000000000000000000000815263ffffffff891660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063867baea590602401600060405180830381600087803b158015611ab057600080fd5b505af1158015611ac4573d6000803e3d6000fd5b50505050505094509492505050565b6000610645611ae183612272565b61228d565b60007f000000000000000000000000000000000000000000000000000000000000000063ffffffff16611b18836122ce565b63ffffffff1614611b55576040517f3eeb1dd400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611b60836122e0565b61011c5490915063ffffffff821610611b7c5750600092915050565b611b9060fb63ffffffff80841690611c2416565b611b99846122ef565b14611ba75750600092915050565b6108298361011c8363ffffffff1681548110611bc557611bc561302c565b600091825260209182902060408051606081018252919092015464ffffffffff808216835265010000000000820416938201939093526bffffffffffffffffffffffff6a010000000000000000000090930492909216908201526122fd565b60208201546000908210611c64576040517f8397c2ad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826020018281548110611c7957611c7961302c565b9060005260206000200154905092915050565b6060611d5c848484886000015189602001518a6040015160408051602081019790975260e095861b7fffffffff00000000000000000000000000000000000000000000000000000000908116888301529490951b909316604486015260d891821b7fffffffffff0000000000000000000000000000000000000000000000000000009081166048870152911b16604d84015260a01b7fffffffffffffffffffffffff00000000000000000000000000000000000000001660528301528051603e818403018152605e909201905290565b95945050505050565b61011c5460009061124b9061139b565b600064ffffffffff821115611431576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203460448201527f30206269747300000000000000000000000000000000000000000000000000006064820152608401610b80565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16611f1a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610b80565b610ad933611795565b602081015460009015611f3857611f386132bb565b60209182018054600181018255600091825292902090910181905590565b6040805160608101825260008082526020820181905291810191909152611f7b612345565b64ffffffffff168152611f8c611709565b64ffffffffff166020820152611fa0612350565b6bffffffffffffffffffffffff16604082015290565b6000611fc0611d65565b61011c805460018101825560009190915283517fadd86a4592312086270d45a94ec1626035e36f7028a1706ab88a5151613929fe9091018054602086015160408701516bffffffffffffffffffffffff166a0100000000000000000000027fffffffffffffffffffff000000000000000000000000ffffffffffffffffffff64ffffffffff92831665010000000000027fffffffffffffffffffffffffffffffffffffffffffff000000000000000000009094169290951691909117919091179290921691909117905590507fc82fd59396134ccdeb4ce594571af6fe8f87d1df40fb6aaf1463ee06d610d0cb6120d983857f000000000000000000000000000000000000000000000000000000000000000085611c8c565b6040516108049190612c91565b600063ffffffff821667ffffffff00000000602085901b166bffffffff0000000000000000604087901b166fffffffff000000000000000000000000606089901b1660808a600181111561213c5761213c612afb565b60ff16901b171717179695505050505050565b606082826040516020016121649291906132ea565b604051602081830303815290604052905092915050565b600061064561218983612272565b6123c0565b60008061219a83612401565b905060006121ba8270ffffffffffffffffffffffffffffffffff16612417565b60018111156121cb576121cb612afb565b03612214576108296121f68270ffffffffffffffffffffffffffffffffff1660009081526020902090565b61220f61220a6122058761244a565b612456565b612497565b6124bd565b61082961223a8270ffffffffffffffffffffffffffffffffff1660009081526020902090565b61220f61224e6122498761244a565b612509565b61254a565b600061226060fb8361255a565b905061226e8161187f611f56565b5050565b805160009060208301612285818361259a565b949350505050565b6000612298826125fd565b611431576040517f6ba041c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061064560206004845b9190612625565b600061064560246004846122d9565b600061064582826020612646565b805160009064ffffffffff1661231284612750565b64ffffffffff161480156108295750816020015164ffffffffff166123368461275f565b64ffffffffff16149392505050565b600061124b43611d75565b600061124b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166334926b296040518163ffffffff1660e01b8152600401602060405180830381865afa158015611672573d6000803e3d6000fd5b60006123cb8261276e565b611431576040517fd082b2a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610645612412826011856122d9565b612823565b60006124368270ffffffffffffffffffffffffffffffffff1660801c90565b60ff16600181111561064557610645612afb565b60008161082981612867565b60006124618261287e565b611431576040517f35c196ef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006106456124b46124a8846128b3565b60009081526020902090565b61220f846128c4565b6000821580156124cb575081155b156124d857506000610645565b6040805160208101859052908101839052606001604051602081830303815290604052805190602001209050610645565b6000612514826128d4565b611431576040517f9d46362800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061064582612910565b612910565b602082015460009061256d84828561293b565b61257784826129f3565b602094850180546001810182556000918252959020909401849055509192915050565b6000806125a78385613248565b90506040518111156125b7575060005b806000036125f1576040517f10bef38600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b608084901b8317612285565b600061260b600c6032613248565b6fffffffffffffffffffffffffffffffff83161492915050565b600080612633858585612646565b602084900360031b1c9150509392505050565b60008160000361265857506000610829565b6020821115612693576040517f31d784a800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6fffffffffffffffffffffffffffffffff84166126b08385613248565b11156126e8576040517fa3b99ded00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600382901b60006126f98660801c90565b909401517f80000000000000000000000000000000000000000000000000000000000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092019190911d16949350505050565b600061064560286005846122d9565b6000610645602d6005846122d9565b60006fffffffffffffffffffffffffffffffff821661278e601183613248565b81101561279e5750600092915050565b60006127a984612a48565b9050600160ff608083901c1611156127c5575060009392505050565b60006127eb6127d383612823565b70ffffffffffffffffffffffffffffffffff16612417565b60018111156127fc576127fc612afb565b036128125761228561280d85612867565b61287e565b61228561281e85612867565b6128d4565b6000600160ff608084901c161115611431576040517f58ebbfbe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610645612877601183613248565b8390612a56565b6000601861288e60206040613248565b6128989190613248565b6fffffffffffffffffffffffffffffffff8316101592915050565b6000610645611696826020856122d9565b6000610645612555836020612a56565b60006fffffffffffffffffffffffffffffffff821660048110156128fb5750600092915050565b610829612909600483613335565b601f161590565b60008061291d8360801c90565b6fffffffffffffffffffffffffffffffff9390931690922092915050565b600161294960206002613468565b6129539190613335565b82111561298c576040517fef5ccf6600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b60208110156129ea57826001166001036129be57818482602081106129b6576129b661302c565b015550505050565b6129db8482602081106129d3576129d361302c565b0154836124bd565b600193841c939092500161298f565b50610acc6132bb565b6000805b6020811015612a415782600116600103612a2757612a208482602081106129d3576129d361302c565b9150612a35565b612a328260006124bd565b91505b600192831c92016129f7565b5092915050565b600061064582826011612625565b60006fffffffffffffffffffffffffffffffff831680831115612aa5576040517fa3b99ded00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61228583612ab38660801c90565b0184830361259a565b73ffffffffffffffffffffffffffffffffffffffff81168114610b9257600080fd5b600060208284031215612af057600080fd5b813561082981612abc565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b805160068110612b3c57612b3c612afb565b825260208181015163ffffffff9081169184019190915260409182015116910152565b606081016106458284612b2a565b600060208284031215612b7f57600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff83168152608081016108296020830184612b2a565b60008060408385031215612bc357600080fd5b8235612bce81612abc565b946020939093013593505050565b63ffffffff81168114610b9257600080fd5b600080600060608486031215612c0357600080fd5b8335612c0e81612bdc565b95602085013595506040909401359392505050565b60005b83811015612c3e578181015183820152602001612c26565b50506000910152565b60008151808452612c5f816020860160208601612c23565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006108296020830184612c47565b60008060208385031215612cb757600080fd5b823567ffffffffffffffff80821115612ccf57600080fd5b818501915085601f830112612ce357600080fd5b813581811115612cf257600080fd5b8660208260051b8501011115612d0757600080fd5b60209290920196919550909350505050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b83811015612d9f578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00185528151805115158452870151878401879052612d8c87850182612c47565b9588019593505090860190600101612d40565b509098975050505050505050565b60008060408385031215612dc057600080fd5b8235612dcb81612bdc565b91506020830135612ddb81612bdc565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f830112612e2657600080fd5b813567ffffffffffffffff80821115612e4157612e41612de6565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715612e8757612e87612de6565b81604052838152866020858801011115612ea057600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600080600060a08688031215612ed857600080fd5b8535612ee381612bdc565b9450602086013593506040860135612efa81612bdc565b925060608601359150608086013567ffffffffffffffff811115612f1d57600080fd5b612f2988828901612e15565b9150509295509295909350565b600080600060608486031215612f4b57600080fd5b8335612f5681612bdc565b92506020840135612f6681612bdc565b9150604084013567ffffffffffffffff811115612f8257600080fd5b612f8e86828701612e15565b9150509250925092565b600060208284031215612faa57600080fd5b813567ffffffffffffffff811115612fc157600080fd5b61228584828501612e15565b600060208284031215612fdf57600080fd5b813561082981612bdc565b815160608201906003811061300157613001612afb565b80835250602083015164ffffffffff8082166020850152806040860151166040850152505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc183360301811261308f57600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126130ce57600080fd5b83018035915067ffffffffffffffff8211156130e957600080fd5b6020019150368190038213156130fe57600080fd5b9250929050565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b63ffffffff828116828216039080821115612a4157612a41613115565b60006060828403121561317357600080fd5b6040516060810181811067ffffffffffffffff8211171561319657613196612de6565b80604052508091508251600681106131ad57600080fd5b815260208301516131bd81612bdc565b602082015260408301516131d081612bdc565b6040919091015292915050565b6000606082840312156131ef57600080fd5b6108298383613161565b6000806080838503121561320c57600080fd5b825161321781612abc565b91506132268460208501613161565b90509250929050565b60006020828403121561324157600080fd5b5051919050565b8082018082111561064557610645613115565b8581528460208201528360408201527fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000008360401b166060820152600082516132aa816078850160208701612c23565b919091016078019695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b7fffffffffffffffffffffffffffffffffff0000000000000000000000000000008360781b16815260008251613327816011850160208701612c23565b919091016011019392505050565b8181038181111561064557610645613115565b600181815b808511156133a157817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561338757613387613115565b8085161561339457918102915b93841c939080029061334d565b509250929050565b6000826133b857506001610645565b816133c557506000610645565b81600181146133db57600281146133e557613401565b6001915050610645565b60ff8411156133f6576133f6613115565b50506001821b610645565b5060208310610133831016604e8410600b8410161715613424575081810a610645565b61342e8383613348565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561346057613460613115565b029392505050565b600061082983836133a956fea26469706673582212209ab634ffccdc2b40f674be443c69bf400699022767c9d83cb887cc64e0b62cdb64736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/OriginEvents.sol\n\n/// @notice A collection of events emitted by the Origin contract\nabstract contract OriginEvents {\n    /**\n     * @notice Emitted when a new message is sent.\n     * @param messageHash   Hash of message; the leaf inserted to the Merkle tree for the message\n     * @param nonce         Nonce of sent message (starts from 1)\n     * @param destination   Destination domain\n     * @param message       Raw bytes of message\n     */\n    event Sent(bytes32 indexed messageHash, uint32 indexed nonce, uint32 indexed destination, bytes message);\n\n    /**\n     * @notice Emitted when a tip withdrawal is completed.\n     * @param actor     Actor address\n     * @param tip       Tip value, denominated in local domain's wei\n     */\n    event TipWithdrawalCompleted(address actor, uint256 tip);\n}\n\n// contracts/events/StateHubEvents.sol\n\n/// @notice A collection of events emitted by the StateHub contract\nabstract contract StateHubEvents {\n    /**\n     * @notice Emitted when a new Origin State is saved after a message was sent.\n     * @param state     Raw payload with state data\n     */\n    event StateSaved(bytes state);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n    /**\n     * @notice Check that a given state is valid: matches the historical state of Origin contract.\n     * Note: any Agent including an invalid state in their snapshot will be slashed\n     * upon providing the snapshot and agent signature for it to Origin contract.\n     * @dev Will revert if any of these is true:\n     *  - State payload is not properly formatted.\n     * @param statePayload      Raw payload with state data\n     * @return isValid          Whether the provided state is valid\n     */\n    function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns the amount of saved states so far.\n     * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n     */\n    function statesAmount() external view returns (uint256);\n\n    /**\n     * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @return statePayload     Raw payload with the latest state data\n     */\n    function suggestLatestState() external view returns (bytes memory statePayload);\n\n    /**\n     * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @param nonce             Historical nonce to form a state\n     * @return statePayload     Raw payload with historical state data\n     */\n    function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/InterfaceGasOracle.sol\n\ninterface InterfaceGasOracle {\n    /**\n     * @notice Fetches the latest gas data for the chain from `Destination` contract,\n     * and uses it to update the oracle values for the requested chain.\n     * @param domain    Domain to update the gas data for\n     */\n    function updateGasData(uint32 domain) external;\n\n    /**\n     * @notice Returns the gas data for the local chain.\n     */\n    function getGasData() external view returns (uint256 paddedGasData);\n\n    /**\n     * @notice Returns the gas data for the given domain, in the decoded format.\n     * @param domain        Domain of chain to get gas data for\n     * @return gasPrice     Gas price for the chain (in Wei per gas unit)\n     * @return dataPrice    Calldata price (in Wei per byte of content)\n     * @return execBuffer   Tx fee safety buffer for message execution (in Wei)\n     * @return amortAttCost Amortized cost for attestation submission (in Wei)\n     * @return etherPrice   Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n     * @return markup       Markup for the message execution (in BWAD)\n     */\n    function getDecodedGasData(uint32 domain)\n        external\n        view\n        returns (\n            uint256 gasPrice,\n            uint256 dataPrice,\n            uint256 execBuffer,\n            uint256 amortAttCost,\n            uint256 etherPrice,\n            uint256 markup\n        );\n\n    /**\n     * @notice Returns the minimum tips for sending a message to a given destination.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return paddedTips       Padded encoded minimum tips information\n     */\n    function getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 paddedTips);\n}\n\n// contracts/interfaces/InterfaceOrigin.sol\n\ninterface InterfaceOrigin {\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /**\n     * @notice Send a message to the recipient located on destination domain.\n     * @dev Recipient has to conform to IMessageRecipient interface, otherwise message won't be delivered.\n     * Will revert if any of these is true:\n     * - `destination` is equal to contract's local domain\n     * - `content` length is greater than `MAX_CONTENT_BYTES`\n     * - `msg.value` is lower than value of minimum tips for the given message\n     * @param destination           Domain of destination chain\n     * @param recipient             Address of recipient on destination chain as bytes32\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param paddedRequest         Padded encoded message execution request on destination chain\n     * @param content               Raw bytes content of message\n     * @return messageNonce         Nonce of the sent message\n     * @return messageHash          Hash of the sent message\n     */\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable returns (uint32 messageNonce, bytes32 messageHash);\n\n    /**\n     * @notice Send a manager message to the destination domain.\n     * @dev This could only be called by AgentManager, which takes care of encoding the calldata payload.\n     * Note: (msgOrigin, proofMaturity) security args will be added to payload on the destination chain\n     * so that the AgentManager could verify where the Manager Message came from and how mature is the proof.\n     * Note: function is not payable, as no tips are required for sending a manager message.\n     * Will revert if `destination` is equal to contract's local domain.\n     * @param destination           Domain of destination chain\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param payload               Payload for calling AgentManager on destination chain (with extra security args)\n     */\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        returns (uint32 messageNonce, bytes32 messageHash);\n\n    // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Withdraws locked base message tips to the recipient.\n     * @dev Could only be called by a local AgentManager.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function withdrawTips(address recipient, uint256 amount) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the minimum tips value for sending a message to a given destination.\n     * @dev Using at least `tipsValue` as `msg.value` for `sendBaseMessage()`\n     * will guarantee that the message will be accepted.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return tipsValue        Minimum tips value for a message to be accepted\n     */\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue);\n}\n\n// contracts/libs/Constants.sol\n\n// Here we define common constants to enable their easier reusing later.\n\n// ══════════════════════════════════ MERKLE ═══════════════════════════════════\n/// @dev Height of the Agent Merkle Tree\nuint256 constant AGENT_TREE_HEIGHT = 32;\n/// @dev Height of the Origin Merkle Tree\nuint256 constant ORIGIN_TREE_HEIGHT = 32;\n/// @dev Height of the Snapshot Merkle Tree. Allows up to 64 leafs, e.g. up to 32 states\nuint256 constant SNAPSHOT_TREE_HEIGHT = 6;\n// ══════════════════════════════════ STRUCTS ══════════════════════════════════\n/// @dev See Attestation.sol: (bytes32,bytes32,uint32,uint40,uint40): 32+32+4+5+5\nuint256 constant ATTESTATION_LENGTH = 78;\n/// @dev See GasData.sol: (uint16,uint16,uint16,uint16,uint16,uint16): 2+2+2+2+2+2\nuint256 constant GAS_DATA_LENGTH = 12;\n/// @dev See Receipt.sol: (uint32,uint32,bytes32,bytes32,uint8,address,address,address): 4+4+32+32+1+20+20+20\nuint256 constant RECEIPT_LENGTH = 133;\n/// @dev See State.sol: (bytes32,uint32,uint32,uint40,uint40,GasData): 32+4+4+5+5+len(GasData)\nuint256 constant STATE_LENGTH = 50 + GAS_DATA_LENGTH;\n/// @dev Maximum amount of states in a single snapshot. Each state produces two leafs in the tree\nuint256 constant SNAPSHOT_MAX_STATES = 1 \u003c\u003c (SNAPSHOT_TREE_HEIGHT - 1);\n// ══════════════════════════════════ MESSAGE ══════════════════════════════════\n/// @dev See Header.sol: (uint8,uint32,uint32,uint32,uint32): 1+4+4+4+4\nuint256 constant HEADER_LENGTH = 17;\n/// @dev See Request.sol: (uint96,uint64,uint32): 12+8+4\nuint256 constant REQUEST_LENGTH = 24;\n/// @dev See Tips.sol: (uint64,uint64,uint64,uint64): 8+8+8+8\nuint256 constant TIPS_LENGTH = 32;\n/// @dev The amount of discarded last bits when encoding tip values\nuint256 constant TIPS_GRANULARITY = 32;\n/// @dev Tip values could be only the multiples of TIPS_MULTIPLIER\nuint256 constant TIPS_MULTIPLIER = 1 \u003c\u003c TIPS_GRANULARITY;\n// ══════════════════════════════ STATEMENT SALTS ══════════════════════════════\n/// @dev Salts for signing various statements\nbytes32 constant ATTESTATION_VALID_SALT = keccak256(\"ATTESTATION_VALID_SALT\");\nbytes32 constant ATTESTATION_INVALID_SALT = keccak256(\"ATTESTATION_INVALID_SALT\");\nbytes32 constant RECEIPT_VALID_SALT = keccak256(\"RECEIPT_VALID_SALT\");\nbytes32 constant RECEIPT_INVALID_SALT = keccak256(\"RECEIPT_INVALID_SALT\");\nbytes32 constant SNAPSHOT_VALID_SALT = keccak256(\"SNAPSHOT_VALID_SALT\");\nbytes32 constant STATE_INVALID_SALT = keccak256(\"STATE_INVALID_SALT\");\n// ═════════════════════════════════ PROTOCOL ══════════════════════════════════\n/// @dev Optimistic period for new agent roots in LightManager\nuint32 constant AGENT_ROOT_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Timeout between the agent root could be proposed and resolved in LightManager\nuint32 constant AGENT_ROOT_PROPOSAL_TIMEOUT = 12 hours;\nuint32 constant BONDING_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Amount of time that the Notary will not be considered active after they won a dispute\nuint32 constant DISPUTE_TIMEOUT_NOTARY = 12 hours;\n/// @dev Amount of time without fresh data from Notaries before contract owner can resolve stuck disputes manually\nuint256 constant FRESH_DATA_TIMEOUT = 4 hours;\n/// @dev Maximum bytes per message = 2 KiB (somewhat arbitrarily set to begin)\nuint256 constant MAX_CONTENT_BYTES = 2 * 2 ** 10;\n/// @dev Maximum value for the summit tip that could be set in GasOracle\nuint256 constant MAX_SUMMIT_TIP = 0.01 ether;\n\n// contracts/libs/Errors.sol\n\n// ══════════════════════════════ INVALID CALLER ═══════════════════════════════\n\nerror CallerNotAgentManager();\nerror CallerNotDestination();\nerror CallerNotInbox();\nerror CallerNotSummit();\n\n// ══════════════════════════════ INCORRECT DATA ═══════════════════════════════\n\nerror IncorrectAttestation();\nerror IncorrectAgentDomain();\nerror IncorrectAgentIndex();\nerror IncorrectAgentProof();\nerror IncorrectAgentRoot();\nerror IncorrectDataHash();\nerror IncorrectDestinationDomain();\nerror IncorrectOriginDomain();\nerror IncorrectSnapshotProof();\nerror IncorrectSnapshotRoot();\nerror IncorrectState();\nerror IncorrectStatesAmount();\nerror IncorrectTipsProof();\nerror IncorrectVersionLength();\n\nerror IncorrectNonce();\nerror IncorrectSender();\nerror IncorrectRecipient();\n\nerror FlagOutOfRange();\nerror IndexOutOfRange();\nerror NonceOutOfRange();\n\nerror OutdatedNonce();\n\nerror UnformattedAttestation();\nerror UnformattedAttestationReport();\nerror UnformattedBaseMessage();\nerror UnformattedCallData();\nerror UnformattedCallDataPrefix();\nerror UnformattedMessage();\nerror UnformattedReceipt();\nerror UnformattedReceiptReport();\nerror UnformattedSignature();\nerror UnformattedSnapshot();\nerror UnformattedState();\nerror UnformattedStateReport();\n\n// ═══════════════════════════════ MERKLE TREES ════════════════════════════════\n\nerror LeafNotProven();\nerror MerkleTreeFull();\nerror NotEnoughLeafs();\nerror TreeHeightTooLow();\n\n// ═════════════════════════════ OPTIMISTIC PERIOD ═════════════════════════════\n\nerror BaseClientOptimisticPeriod();\nerror MessageOptimisticPeriod();\nerror SlashAgentOptimisticPeriod();\nerror WithdrawTipsOptimisticPeriod();\nerror ZeroProofMaturity();\n\n// ═══════════════════════════════ AGENT MANAGER ═══════════════════════════════\n\nerror AgentNotGuard();\nerror AgentNotNotary();\n\nerror AgentCantBeAdded();\nerror AgentNotActive();\nerror AgentNotActiveNorUnstaking();\nerror AgentNotFraudulent();\nerror AgentNotUnstaking();\nerror AgentUnknown();\n\nerror AgentRootNotProposed();\nerror AgentRootTimeoutNotOver();\n\nerror NotStuck();\n\nerror DisputeAlreadyResolved();\nerror DisputeNotOpened();\nerror DisputeTimeoutNotOver();\nerror GuardInDispute();\nerror NotaryInDispute();\n\nerror MustBeSynapseDomain();\nerror SynapseDomainForbidden();\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\nerror AlreadyExecuted();\nerror AlreadyFailed();\nerror DuplicatedSnapshotRoot();\nerror IncorrectMagicValue();\nerror GasLimitTooLow();\nerror GasSuppliedTooLow();\n\n// ══════════════════════════════════ ORIGIN ═══════════════════════════════════\n\nerror ContentLengthTooBig();\nerror EthTransferFailed();\nerror InsufficientEthBalance();\n\n// ════════════════════════════════ GAS ORACLE ═════════════════════════════════\n\nerror LocalGasDataNotSet();\nerror RemoteGasDataNotSet();\n\n// ═══════════════════════════════════ TIPS ════════════════════════════════════\n\nerror SummitTipTooHigh();\nerror TipsClaimMoreThanEarned();\nerror TipsClaimZero();\nerror TipsOverflow();\nerror TipsValueTooLow();\n\n// ════════════════════════════════ MEMORY VIEW ════════════════════════════════\n\nerror IndexedTooMuch();\nerror ViewOverrun();\nerror OccupiedMemory();\nerror UnallocatedMemory();\nerror PrecompileOutOfGas();\n\n// ═════════════════════════════════ MULTICALL ═════════════════════════════════\n\nerror MulticallFailed();\n\n// contracts/libs/TypeCasts.sol\n\nlibrary TypeCasts {\n    // alignment preserving cast\n    function addressToBytes32(address addr) internal pure returns (bytes32) {\n        return bytes32(uint256(uint160(addr)));\n    }\n\n    // alignment preserving cast\n    function bytes32ToAddress(bytes32 buf) internal pure returns (address) {\n        return address(uint160(uint256(buf)));\n    }\n}\n\n// contracts/libs/stack/Number.sol\n\n/// Number is a compact representation of uint256, that is fit into 16 bits\n/// with the maximum relative error under 0.4%.\ntype Number is uint16;\n\nusing NumberLib for Number global;\n\n/// # Number\n/// Library for compact representation of uint256 numbers.\n/// - Number is stored using mantissa and exponent, each occupying 8 bits.\n/// - Numbers under 2**8 are stored as `mantissa` with `exponent = 0xFF`.\n/// - Numbers at least 2**8 are approximated as `(256 + mantissa) \u003c\u003c exponent`\n/// \u003e - `0 \u003c= mantissa \u003c 256`\n/// \u003e - `0 \u003c= exponent \u003c= 247` (`256 * 2**248` doesn't fit into uint256)\n/// # Number stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type  | Bytes |\n/// | ---------- | -------- | ----- | ----- |\n/// | (002..001] | mantissa | uint8 | 1     |\n/// | (001..000] | exponent | uint8 | 1     |\n\nlibrary NumberLib {\n    /// @dev Amount of bits to shift to mantissa field\n    uint16 private constant SHIFT_MANTISSA = 8;\n\n    /// @notice For bwad math (binary wad) we use 2**64 as \"wad\" unit.\n    /// @dev We are using not using 10**18 as wad, because it is not stored precisely in NumberLib.\n    uint256 internal constant BWAD_SHIFT = 64;\n    uint256 internal constant BWAD = 1 \u003c\u003c BWAD_SHIFT;\n    /// @notice ~0.1% in bwad units.\n    uint256 internal constant PER_MILLE_SHIFT = BWAD_SHIFT - 10;\n    uint256 internal constant PER_MILLE = 1 \u003c\u003c PER_MILLE_SHIFT;\n\n    /// @notice Compresses uint256 number into 16 bits.\n    function compress(uint256 value) internal pure returns (Number) {\n        // Find `msb` such as `2**msb \u003c= value \u003c 2**(msb + 1)`\n        uint256 msb = mostSignificantBit(value);\n        // We want to preserve 9 bits of precision.\n        // The highest bit is always 1, so we can skip it.\n        // The remaining 8 highest bits are stored as mantissa.\n        if (msb \u003c 8) {\n            // Value is less than 2**8, so we can use value as mantissa with \"-1\" exponent.\n            return _encode(uint8(value), 0xFF);\n        } else {\n            // We use `msb - 8` as exponent otherwise. Note that `exponent \u003e= 0`.\n            unchecked {\n                uint256 exponent = msb - 8;\n                // Shifting right by `msb-8` bits will shift the \"remaining 8 highest bits\" into the 8 lowest bits.\n                // uint8() will truncate the highest bit.\n                return _encode(uint8(value \u003e\u003e exponent), uint8(exponent));\n            }\n        }\n    }\n\n    /// @notice Decompresses 16 bits number into uint256.\n    /// @dev The outcome is an approximation of the original number: `(value - value / 256) \u003c number \u003c= value`.\n    function decompress(Number number) internal pure returns (uint256 value) {\n        // Isolate 8 highest bits as the mantissa.\n        uint256 mantissa = Number.unwrap(number) \u003e\u003e SHIFT_MANTISSA;\n        // This will truncate the highest bits, leaving only the exponent.\n        uint256 exponent = uint8(Number.unwrap(number));\n        if (exponent == 0xFF) {\n            return mantissa;\n        } else {\n            unchecked {\n                return (256 + mantissa) \u003c\u003c (exponent);\n            }\n        }\n    }\n\n    /// @dev Returns the most significant bit of `x`\n    /// https://solidity-by-example.org/bitwise/\n    function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\n        // To find `msb` we determine it bit by bit, starting from the highest one.\n        // `0 \u003c= msb \u003c= 255`, so we start from the highest bit, 1\u003c\u003c7 == 128.\n        // If `x` is at least 2**128, then the highest bit of `x` is at least 128.\n        // solhint-disable no-inline-assembly\n        assembly {\n            // `f` is set to 1\u003c\u003c7 if `x \u003e= 2**128` and to 0 otherwise.\n            let f := shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\n            // If `x \u003e= 2**128` then set `msb` highest bit to 1 and shift `x` right by 128.\n            // Otherwise, `msb` remains 0 and `x` remains unchanged.\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        // `x` is now at most 2**128 - 1. Continue the same way, the next highest bit is 1\u003c\u003c6 == 64.\n        assembly {\n            // `f` is set to 1\u003c\u003c6 if `x \u003e= 2**64` and to 0 otherwise.\n            let f := shl(6, gt(x, 0xFFFFFFFFFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c5 if `x \u003e= 2**32` and to 0 otherwise.\n            let f := shl(5, gt(x, 0xFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c4 if `x \u003e= 2**16` and to 0 otherwise.\n            let f := shl(4, gt(x, 0xFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c3 if `x \u003e= 2**8` and to 0 otherwise.\n            let f := shl(3, gt(x, 0xFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c2 if `x \u003e= 2**4` and to 0 otherwise.\n            let f := shl(2, gt(x, 0xF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c1 if `x \u003e= 2**2` and to 0 otherwise.\n            let f := shl(1, gt(x, 0x3))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1 if `x \u003e= 2**1` and to 0 otherwise.\n            let f := gt(x, 0x1)\n            msb := or(msb, f)\n        }\n    }\n\n    /// @dev Wraps (mantissa, exponent) pair into Number.\n    function _encode(uint8 mantissa, uint8 exponent) private pure returns (Number) {\n        // Casts below are upcasts, so they are safe.\n        return Number.wrap(uint16(mantissa) \u003c\u003c SHIFT_MANTISSA | uint16(exponent));\n    }\n}\n\n// contracts/libs/stack/Request.sol\n\n/// Request is encoded data with \"message execution request\".\ntype Request is uint192;\n\nusing RequestLib for Request global;\n\n/// Library for formatting _the request part_ of _the base messages_.\n/// - Request represents a message sender requirements for the message execution on the destination chain.\n/// - Request occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n/// \u003e gasDrop field is included for future compatibility and is ignored at the moment.\n///\n/// # Request stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type   | Bytes | Description                                          |\n/// | ---------- | -------- | ------ | ----- | ---------------------------------------------------- |\n/// | (024..012] | gasDrop  | uint96 | 12    | Minimum amount of gas token to drop to the recipient |\n/// | (012..004] | gasLimit | uint64 | 8     | Minimum amount of gas units to supply for execution  |\n/// | (004..000] | version  | uint32 | 4     | Base message version to pass to the recipient        |\n\nlibrary RequestLib {\n    /// @dev Amount of bits to shift to gasDrop field\n    uint192 private constant SHIFT_GAS_DROP = 12 * 8;\n    /// @dev Amount of bits to shift to gasLimit field\n    uint192 private constant SHIFT_GAS_LIMIT = 4 * 8;\n\n    /// @notice Returns an encoded request with the given fields\n    /// @param gasDrop_     Minimum amount of gas token to drop to the recipient (ignored at the moment)\n    /// @param gasLimit_    Minimum amount of gas units to supply for execution\n    /// @param version_     Base message version to pass to the recipient\n    function encodeRequest(uint96 gasDrop_, uint64 gasLimit_, uint32 version_) internal pure returns (Request) {\n        // Casts below are upcasts, so they are safe\n        return Request.wrap(uint192(gasDrop_) \u003c\u003c SHIFT_GAS_DROP | uint192(gasLimit_) \u003c\u003c SHIFT_GAS_LIMIT | version_);\n    }\n\n    /// @notice Wraps the padded encoded request into a Request-typed value.\n    /// @dev The \"padded\" request is simply an encoded request casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded requests\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedRequest) internal pure returns (Request) {\n        // Casting to uint192 will truncate the highest bits, which is the behavior we want\n        return Request.wrap(uint192(paddedRequest));\n    }\n\n    /// @notice Returns the requested of gas token to drop to the recipient.\n    function gasDrop(Request request) internal pure returns (uint96) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return uint96(Request.unwrap(request) \u003e\u003e SHIFT_GAS_DROP);\n    }\n\n    /// @notice Returns the requested minimum amount of gas units to supply for execution.\n    function gasLimit(Request request) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Request.unwrap(request) \u003e\u003e SHIFT_GAS_LIMIT);\n    }\n\n    /// @notice Returns the requested base message version to pass to the recipient.\n    function version(Request request) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Request.unwrap(request));\n    }\n}\n\n// node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        require(value \u003c= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        require(value \u003c= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        require(value \u003c= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value \u003c= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        require(value \u003c= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        require(value \u003c= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        require(value \u003c= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        require(value \u003c= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        require(value \u003c= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        require(value \u003c= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        require(value \u003c= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        require(value \u003c= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        require(value \u003c= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        require(value \u003c= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        require(value \u003c= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value \u003c= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        require(value \u003c= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        require(value \u003c= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        require(value \u003c= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value \u003c= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        require(value \u003c= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        require(value \u003c= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        require(value \u003c= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value \u003c= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        require(value \u003c= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        require(value \u003c= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        require(value \u003c= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value \u003c= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        require(value \u003c= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value \u003c= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value \u003c= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     *\n     * _Available since v3.0._\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value \u003e= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     *\n     * _Available since v3.0._\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value \u003c= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     *\n     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length \u003e 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance \u003e= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance \u003e= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length \u003e 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n\n// contracts/base/MultiCallable.sol\n\n/// @notice Collection of Multicall utilities. Fork of Multicall3:\n/// https://github.com/mds1/multicall/blob/master/src/Multicall3.sol\nabstract contract MultiCallable {\n    struct Call {\n        bool allowFailure;\n        bytes callData;\n    }\n\n    struct Result {\n        bool success;\n        bytes returnData;\n    }\n\n    /// @notice Aggregates a few calls to this contract into one multicall without modifying `msg.sender`.\n    function multicall(Call[] calldata calls) external returns (Result[] memory callResults) {\n        uint256 amount = calls.length;\n        callResults = new Result[](amount);\n        Call calldata call_;\n        for (uint256 i = 0; i \u003c amount;) {\n            call_ = calls[i];\n            Result memory result = callResults[i];\n            // We perform a delegate call to ourselves here. Delegate call does not modify `msg.sender`, so\n            // this will have the same effect as if `msg.sender` performed all the calls themselves one by one.\n            // solhint-disable-next-line avoid-low-level-calls\n            (result.success, result.returnData) = address(this).delegatecall(call_.callData);\n            // solhint-disable-next-line no-inline-assembly\n            assembly {\n                // Revert if the call fails and failure is not allowed\n                // `allowFailure := calldataload(call_)` and `success := mload(result)`\n                if iszero(or(calldataload(call_), mload(result))) {\n                    // Revert with `0x4d6a2328` (function selector for `MulticallFailed()`)\n                    mstore(0x00, 0x4d6a232800000000000000000000000000000000000000000000000000000000)\n                    revert(0x00, 0x04)\n                }\n            }\n            unchecked {\n                ++i;\n            }\n        }\n    }\n}\n\n// contracts/base/Version.sol\n\n/**\n * @title Versioned\n * @notice Version getter for contracts. Doesn't use any storage slots, meaning\n * it will never cause any troubles with the upgradeable contracts. For instance, this contract\n * can be added or removed from the inheritance chain without shifting the storage layout.\n */\nabstract contract Versioned {\n    /**\n     * @notice Struct that is mimicking the storage layout of a string with 32 bytes or less.\n     * Length is limited by 32, so the whole string payload takes two memory words:\n     * @param length    String length\n     * @param data      String characters\n     */\n    struct _ShortString {\n        uint256 length;\n        bytes32 data;\n    }\n\n    /// @dev Length of the \"version string\"\n    uint256 private immutable _length;\n    /// @dev Bytes representation of the \"version string\".\n    /// Strings with length over 32 are not supported!\n    bytes32 private immutable _data;\n\n    constructor(string memory version_) {\n        _length = bytes(version_).length;\n        if (_length \u003e 32) revert IncorrectVersionLength();\n        // bytes32 is left-aligned =\u003e this will store the byte representation of the string\n        // with the trailing zeroes to complete the 32-byte word\n        _data = bytes32(bytes(version_));\n    }\n\n    function version() external view returns (string memory versionString) {\n        // Load the immutable values to form the version string\n        _ShortString memory str = _ShortString(_length, _data);\n        // The only way to do this cast is doing some dirty assembly\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            versionString := str\n        }\n    }\n}\n\n// contracts/libs/ChainContext.sol\n\n/// @notice Library for accessing chain context variables as tightly packed integers.\n/// Messaging contracts should rely on this library for accessing chain context variables\n/// instead of doing the casting themselves.\nlibrary ChainContext {\n    using SafeCast for uint256;\n\n    /// @notice Returns the current block number as uint40.\n    /// @dev Reverts if block number is greater than 40 bits, which is not supposed to happen\n    /// until the block.timestamp overflows (assuming block time is at least 1 second).\n    function blockNumber() internal view returns (uint40) {\n        return block.number.toUint40();\n    }\n\n    /// @notice Returns the current block timestamp as uint40.\n    /// @dev Reverts if block timestamp is greater than 40 bits, which is\n    /// supposed to happen approximately in year 36835.\n    function blockTimestamp() internal view returns (uint40) {\n        return block.timestamp.toUint40();\n    }\n\n    /// @notice Returns the chain id as uint32.\n    /// @dev Reverts if chain id is greater than 32 bits, which is not\n    /// supposed to happen in production.\n    function chainId() internal view returns (uint32) {\n        return block.chainid.toUint32();\n    }\n}\n\n// contracts/libs/Structures.sol\n\n// Here we define common enums and structures to enable their easier reusing later.\n\n// ═══════════════════════════════ AGENT STATUS ════════════════════════════════\n\n/// @dev Potential statuses for the off-chain bonded agent:\n/// - Unknown: never provided a bond =\u003e signature not valid\n/// - Active: has a bond in BondingManager =\u003e signature valid\n/// - Unstaking: has a bond in BondingManager, initiated the unstaking =\u003e signature not valid\n/// - Resting: used to have a bond in BondingManager, successfully unstaked =\u003e signature not valid\n/// - Fraudulent: proven to commit fraud, value in Merkle Tree not updated =\u003e signature not valid\n/// - Slashed: proven to commit fraud, value in Merkle Tree was updated =\u003e signature not valid\n/// Unstaked agent could later be added back to THE SAME domain by staking a bond again.\n/// Honest agent: Unknown -\u003e Active -\u003e unstaking -\u003e Resting -\u003e Active ...\n/// Malicious agent: Unknown -\u003e Active -\u003e Fraudulent -\u003e Slashed\n/// Malicious agent: Unknown -\u003e Active -\u003e Unstaking -\u003e Fraudulent -\u003e Slashed\nenum AgentFlag {\n    Unknown,\n    Active,\n    Unstaking,\n    Resting,\n    Fraudulent,\n    Slashed\n}\n\n/// @notice Struct for storing an agent in the BondingManager contract.\nstruct AgentStatus {\n    AgentFlag flag;\n    uint32 domain;\n    uint32 index;\n}\n// 184 bits available for tight packing\n\nusing StructureUtils for AgentStatus global;\n\n/// @notice Potential statuses of an agent in terms of being in dispute\n/// - None: agent is not in dispute\n/// - Pending: agent is in unresolved dispute\n/// - Slashed: agent was in dispute that lead to agent being slashed\n/// Note: agent who won the dispute has their status reset to None\nenum DisputeFlag {\n    None,\n    Pending,\n    Slashed\n}\n\n/// @notice Struct for storing dispute status of an agent.\n/// @param flag         Dispute flag: None/Pending/Slashed.\n/// @param openedAt     Timestamp when the latest agent dispute was opened (zero if not opened).\n/// @param resolvedAt   Timestamp when the latest agent dispute was resolved (zero if not resolved).\nstruct DisputeStatus {\n    DisputeFlag flag;\n    uint40 openedAt;\n    uint40 resolvedAt;\n}\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\n/// @notice Struct representing the status of Destination contract.\n/// @param snapRootTime     Timestamp when latest snapshot root was accepted\n/// @param agentRootTime    Timestamp when latest agent root was accepted\n/// @param notaryIndex      Index of Notary who signed the latest agent root\nstruct DestinationStatus {\n    uint40 snapRootTime;\n    uint40 agentRootTime;\n    uint32 notaryIndex;\n}\n\n// ═══════════════════════════════ EXECUTION HUB ═══════════════════════════════\n\n/// @notice Potential statuses of the message in Execution Hub.\n/// - None: there hasn't been a valid attempt to execute the message yet\n/// - Failed: there was a valid attempt to execute the message, but recipient reverted\n/// - Success: there was a valid attempt to execute the message, and recipient did not revert\n/// Note: message can be executed until its status is Success\nenum MessageStatus {\n    None,\n    Failed,\n    Success\n}\n\nlibrary StructureUtils {\n    /// @notice Checks that Agent is Active\n    function verifyActive(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active) {\n            revert AgentNotActive();\n        }\n    }\n\n    /// @notice Checks that Agent is Unstaking\n    function verifyUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Unstaking) {\n            revert AgentNotUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Active or Unstaking\n    function verifyActiveUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active \u0026\u0026 status.flag != AgentFlag.Unstaking) {\n            revert AgentNotActiveNorUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Fraudulent\n    function verifyFraudulent(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Fraudulent) {\n            revert AgentNotFraudulent();\n        }\n    }\n\n    /// @notice Checks that Agent is not Unknown\n    function verifyKnown(AgentStatus memory status) internal pure {\n        if (status.flag == AgentFlag.Unknown) {\n            revert AgentUnknown();\n        }\n    }\n}\n\n// contracts/libs/memory/MemView.sol\n\n/// @dev MemView is an untyped view over a portion of memory to be used instead of `bytes memory`\ntype MemView is uint256;\n\n/// @dev Attach library functions to MemView\nusing MemViewLib for MemView global;\n\n/// @notice Library for operations with the memory views.\n/// Forked from https://github.com/summa-tx/memview-sol with several breaking changes:\n/// - The codebase is ported to Solidity 0.8\n/// - Custom errors are added\n/// - The runtime type checking is replaced with compile-time check provided by User-Defined Value Types\n///   https://docs.soliditylang.org/en/latest/types.html#user-defined-value-types\n/// - uint256 is used as the underlying type for the \"memory view\" instead of bytes29.\n///   It is wrapped into MemView custom type in order not to be confused with actual integers.\n/// - Therefore the \"type\" field is discarded, allowing to allocate 16 bytes for both view location and length\n/// - The documentation is expanded\n/// - Library functions unused by the rest of the codebase are removed\n//  - Very pretty code separators are added :)\nlibrary MemViewLib {\n    /// @notice Stack layout for uint256 (from highest bits to lowest)\n    /// (32 .. 16]      loc     16 bytes    Memory address of underlying bytes\n    /// (16 .. 00]      len     16 bytes    Length of underlying bytes\n\n    // ═══════════════════════════════════════════ BUILDING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Instantiate a new untyped memory view. This should generally not be called directly.\n     * Prefer `ref` wherever possible.\n     * @param loc_          The memory address\n     * @param len_          The length\n     * @return The new view with the specified location and length\n     */\n    function build(uint256 loc_, uint256 len_) internal pure returns (MemView) {\n        uint256 end_ = loc_ + len_;\n        // Make sure that a view is not constructed that points to unallocated memory\n        // as this could be indicative of a buffer overflow attack\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            if gt(end_, mload(0x40)) { end_ := 0 }\n        }\n        if (end_ == 0) {\n            revert UnallocatedMemory();\n        }\n        return _unsafeBuildUnchecked(loc_, len_);\n    }\n\n    /**\n     * @notice Instantiate a memory view from a byte array.\n     * @dev Note that due to Solidity memory representation, it is not possible to\n     * implement a deref, as the `bytes` type stores its len in memory.\n     * @param arr           The byte array\n     * @return The memory view over the provided byte array\n     */\n    function ref(bytes memory arr) internal pure returns (MemView) {\n        uint256 len_ = arr.length;\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 loc_;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // We add 0x20, so that the view starts exactly where the array data starts\n            loc_ := add(arr, 0x20)\n        }\n        return build(loc_, len_);\n    }\n\n    // ════════════════════════════════════════════ CLONING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to the new memory.\n     * @param memView       The memory view\n     * @return arr          The cloned byte array\n     */\n    function clone(MemView memView) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        unchecked {\n            _unsafeCopyTo(memView, ptr + 0x20);\n        }\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 len_ = memView.len();\n        uint256 footprint_ = memView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    /**\n     * @notice Copies all views, joins them into a new bytearray.\n     * @param memViews      The memory views\n     * @return arr          The new byte array with joined data behind the given views\n     */\n    function join(MemView[] memory memViews) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        MemView newView;\n        unchecked {\n            newView = _unsafeJoin(memViews, ptr + 0x20);\n        }\n        uint256 len_ = newView.len();\n        uint256 footprint_ = newView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    // ══════════════════════════════════════════ INSPECTING MEMORY VIEW ═══════════════════════════════════════════════\n\n    /**\n     * @notice Returns the memory address of the underlying bytes.\n     * @param memView       The memory view\n     * @return loc_         The memory address\n     */\n    function loc(MemView memView) internal pure returns (uint256 loc_) {\n        // loc is stored in the highest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u003e\u003e 128;\n    }\n\n    /**\n     * @notice Returns the number of bytes of the view.\n     * @param memView       The memory view\n     * @return len_         The length of the view\n     */\n    function len(MemView memView) internal pure returns (uint256 len_) {\n        // len is stored in the lowest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u0026 type(uint128).max;\n    }\n\n    /**\n     * @notice Returns the endpoint of `memView`.\n     * @param memView       The memory view\n     * @return end_         The endpoint of `memView`\n     */\n    function end(MemView memView) internal pure returns (uint256 end_) {\n        // The endpoint never overflows uint128, let alone uint256, so we could use unchecked math here\n        unchecked {\n            return memView.loc() + memView.len();\n        }\n    }\n\n    /**\n     * @notice Returns the number of memory words this memory view occupies, rounded up.\n     * @param memView       The memory view\n     * @return words_       The number of memory words\n     */\n    function words(MemView memView) internal pure returns (uint256 words_) {\n        // returning ceil(length / 32.0)\n        unchecked {\n            return (memView.len() + 31) \u003e\u003e 5;\n        }\n    }\n\n    /**\n     * @notice Returns the in-memory footprint of a fresh copy of the view.\n     * @param memView       The memory view\n     * @return footprint_   The in-memory footprint of a fresh copy of the view.\n     */\n    function footprint(MemView memView) internal pure returns (uint256 footprint_) {\n        // words() * 32\n        return memView.words() \u003c\u003c 5;\n    }\n\n    // ════════════════════════════════════════════ HASHING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the keccak256 hash of the underlying memory\n     * @param memView       The memory view\n     * @return digest       The keccak256 hash of the underlying memory\n     */\n    function keccak(MemView memView) internal pure returns (bytes32 digest) {\n        uint256 loc_ = memView.loc();\n        uint256 len_ = memView.len();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            digest := keccak256(loc_, len_)\n        }\n    }\n\n    /**\n     * @notice Adds a salt to the keccak256 hash of the underlying data and returns the keccak256 hash of the\n     * resulting data.\n     * @param memView       The memory view\n     * @return digestSalted keccak256(salt, keccak256(memView))\n     */\n    function keccakSalted(MemView memView, bytes32 salt) internal pure returns (bytes32 digestSalted) {\n        return keccak256(bytes.concat(salt, memView.keccak()));\n    }\n\n    // ════════════════════════════════════════════ SLICING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Safe slicing without memory modification.\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the given index\n     */\n    function slice(MemView memView, uint256 index_, uint256 len_) internal pure returns (MemView) {\n        uint256 loc_ = memView.loc();\n        // Ensure it doesn't overrun the view\n        if (loc_ + index_ + len_ \u003e memView.end()) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // loc_ + index_ \u003c= memView.end()\n            return build({loc_: loc_ + index_, len_: len_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing bytes from `index` to end(memView).\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @return The new view for the slice starting from the given index until the initial view endpoint\n     */\n    function sliceFrom(MemView memView, uint256 index_) internal pure returns (MemView) {\n        uint256 len_ = memView.len();\n        // Ensure it doesn't overrun the view\n        if (index_ \u003e len_) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // index_ \u003c= len_ =\u003e memView.loc() + index_ \u003c= memView.loc() + memView.len() == memView.end()\n            return build({loc_: memView.loc() + index_, len_: len_ - index_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the first `len` bytes.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the initial view beginning\n     */\n    function prefix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        return memView.slice({index_: 0, len_: len_});\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the last `len` byte.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length until the initial view endpoint\n     */\n    function postfix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        uint256 viewLen = memView.len();\n        // Ensure it doesn't overrun the view\n        if (len_ \u003e viewLen) {\n            revert ViewOverrun();\n        }\n        // Could do the unchecked math due to the check above\n        uint256 index_;\n        unchecked {\n            index_ = viewLen - len_;\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // len_ \u003c= memView.len() =\u003e memView.loc() \u003c= loc_ \u003c= memView.end()\n            return build({loc_: memView.loc() + viewLen - len_, len_: len_});\n        }\n    }\n\n    // ═══════════════════════════════════════════ INDEXING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Load up to 32 bytes from the view onto the stack.\n     * @dev Returns a bytes32 with only the `bytes_` HIGHEST bytes set.\n     * This can be immediately cast to a smaller fixed-length byte array.\n     * To automatically cast to an integer, use `indexUint`.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return result       The 32 byte result having only `bytes_` highest bytes set\n     */\n    function index(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (bytes32 result) {\n        if (bytes_ == 0) {\n            return bytes32(0);\n        }\n        // Can't load more than 32 bytes to the stack in one go\n        if (bytes_ \u003e 32) {\n            revert IndexedTooMuch();\n        }\n        // The last indexed byte should be within view boundaries\n        if (index_ + bytes_ \u003e memView.len()) {\n            revert ViewOverrun();\n        }\n        uint256 bitLength = bytes_ \u003c\u003c 3; // bytes_ * 8\n        uint256 loc_ = memView.loc();\n        // Get a mask with `bitLength` highest bits set\n        uint256 mask;\n        // 0x800...00 binary representation is 100...00\n        // sar stands for \"signed arithmetic shift\": https://en.wikipedia.org/wiki/Arithmetic_shift\n        // sar(N-1, 100...00) = 11...100..00, with exactly N highest bits set to 1\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            mask := sar(sub(bitLength, 1), 0x8000000000000000000000000000000000000000000000000000000000000000)\n        }\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load a full word using index offset, and apply mask to ignore non-relevant bytes\n            result := and(mload(add(loc_, index_)), mask)\n        }\n    }\n\n    /**\n     * @notice Parse an unsigned integer from the view at `index`.\n     * @dev Requires that the view have \u003e= `bytes_` bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return The unsigned integer\n     */\n    function indexUint(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (uint256) {\n        bytes32 indexedBytes = memView.index(index_, bytes_);\n        // `index()` returns left-aligned `bytes_`, while integers are right-aligned\n        // Shifting here to right-align with the full 32 bytes word: need to shift right `(32 - bytes_)` bytes\n        unchecked {\n            // memView.index() reverts when bytes_ \u003e 32, thus unchecked math\n            return uint256(indexedBytes) \u003e\u003e ((32 - bytes_) \u003c\u003c 3);\n        }\n    }\n\n    /**\n     * @notice Parse an address from the view at `index`.\n     * @dev Requires that the view have \u003e= 20 bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @return The address\n     */\n    function indexAddress(MemView memView, uint256 index_) internal pure returns (address) {\n        // index 20 bytes as `uint160`, and then cast to `address`\n        return address(uint160(memView.indexUint(index_, 20)));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns a memory view over the specified memory location\n    /// without checking if it points to unallocated memory.\n    function _unsafeBuildUnchecked(uint256 loc_, uint256 len_) private pure returns (MemView) {\n        // There is no scenario where loc or len would overflow uint128, so we omit this check.\n        // We use the highest 128 bits to encode the location and the lowest 128 bits to encode the length.\n        return MemView.wrap((loc_ \u003c\u003c 128) | len_);\n    }\n\n    /**\n     * @notice Copy the view to a location, return an unsafe memory reference\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memView       The memory view\n     * @param newLoc        The new location to copy the underlying view data\n     * @return The memory view over the unsafe memory with the copied underlying data\n     */\n    function _unsafeCopyTo(MemView memView, uint256 newLoc) private view returns (MemView) {\n        uint256 len_ = memView.len();\n        uint256 oldLoc = memView.loc();\n\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (newLoc \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        bool res;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // use the identity precompile (0x04) to copy\n            res := staticcall(gas(), 0x04, oldLoc, len_, newLoc, len_)\n        }\n        if (!res) revert PrecompileOutOfGas();\n        return _unsafeBuildUnchecked({loc_: newLoc, len_: len_});\n    }\n\n    /**\n     * @notice Join the views in memory, return an unsafe reference to the memory.\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memViews      The memory views\n     * @return The conjoined view pointing to the new memory\n     */\n    function _unsafeJoin(MemView[] memory memViews, uint256 location) private view returns (MemView) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (location \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        // Copy the views to the specified location one by one, by tracking the amount of copied bytes so far\n        uint256 offset = 0;\n        for (uint256 i = 0; i \u003c memViews.length;) {\n            MemView memView = memViews[i];\n            // We can use the unchecked math here as location + sum(view.length) will never overflow uint256\n            unchecked {\n                _unsafeCopyTo(memView, location + offset);\n                offset += memView.len();\n                ++i;\n            }\n        }\n        return _unsafeBuildUnchecked({loc_: location, len_: offset});\n    }\n}\n\n// contracts/libs/merkle/MerkleMath.sol\n\nlibrary MerkleMath {\n    // ═════════════════════════════════════════ BASIC MERKLE CALCULATIONS ═════════════════════════════════════════════\n\n    /**\n     * @notice Calculates the merkle root for the given leaf and merkle proof.\n     * @dev Will revert if proof length exceeds the tree height.\n     * @param index     Index of `leaf` in tree\n     * @param leaf      Leaf of the merkle tree\n     * @param proof     Proof of inclusion of `leaf` in the tree\n     * @param height    Height of the merkle tree\n     * @return root_    Calculated Merkle Root\n     */\n    function proofRoot(uint256 index, bytes32 leaf, bytes32[] memory proof, uint256 height)\n        internal\n        pure\n        returns (bytes32 root_)\n    {\n        // Proof length could not exceed the tree height\n        uint256 proofLen = proof.length;\n        if (proofLen \u003e height) revert TreeHeightTooLow();\n        root_ = leaf;\n        /// @dev Apply unchecked to all ++h operations\n        unchecked {\n            // Go up the tree levels from the leaf following the proof\n            for (uint256 h = 0; h \u003c proofLen; ++h) {\n                // Get a sibling node on current level: this is proof[h]\n                root_ = getParent(root_, proof[h], index, h);\n            }\n            // Go up to the root: the remaining siblings are EMPTY\n            for (uint256 h = proofLen; h \u003c height; ++h) {\n                root_ = getParent(root_, bytes32(0), index, h);\n            }\n        }\n    }\n\n    /**\n     * @notice Calculates the parent of a node on the path from one of the leafs to root.\n     * @param node          Node on a path from tree leaf to root\n     * @param sibling       Sibling for a given node\n     * @param leafIndex     Index of the tree leaf\n     * @param nodeHeight    \"Level height\" for `node` (ZERO for leafs, ORIGIN_TREE_HEIGHT for root)\n     */\n    function getParent(bytes32 node, bytes32 sibling, uint256 leafIndex, uint256 nodeHeight)\n        internal\n        pure\n        returns (bytes32 parent)\n    {\n        // Index for `node` on its \"tree level\" is (leafIndex / 2**height)\n        // \"Left child\" has even index, \"right child\" has odd index\n        if ((leafIndex \u003e\u003e nodeHeight) \u0026 1 == 0) {\n            // Left child\n            return getParent(node, sibling);\n        } else {\n            // Right child\n            return getParent(sibling, node);\n        }\n    }\n\n    /// @notice Calculates the parent of tow nodes in the merkle tree.\n    /// @dev We use implementation with H(0,0) = 0\n    /// This makes EVERY empty node in the tree equal to ZERO,\n    /// saving us from storing H(0,0), H(H(0,0), H(0, 0)), and so on\n    /// @param leftChild    Left child of the calculated node\n    /// @param rightChild   Right child of the calculated node\n    /// @return parent      Value for the node having above mentioned children\n    function getParent(bytes32 leftChild, bytes32 rightChild) internal pure returns (bytes32 parent) {\n        if (leftChild == bytes32(0) \u0026\u0026 rightChild == bytes32(0)) {\n            return 0;\n        } else {\n            return keccak256(bytes.concat(leftChild, rightChild));\n        }\n    }\n\n    // ════════════════════════════════ ROOT/PROOF CALCULATION FOR A LIST OF LEAFS ═════════════════════════════════════\n\n    /**\n     * @notice Calculates merkle root for a list of given leafs.\n     * Merkle Tree is constructed by padding the list with ZERO values for leafs until list length is `2**height`.\n     * Merkle Root is calculated for the constructed tree, and then saved in `leafs[0]`.\n     * \u003e Note:\n     * \u003e - `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * \u003e - Caller is expected not to reuse `hashes` list after the call, and only use `leafs[0]` value,\n     * which is guaranteed to contain the calculated merkle root.\n     * \u003e - root is calculated using the `H(0,0) = 0` Merkle Tree implementation. See MerkleTree.sol for details.\n     * @dev Amount of leaves should be at most `2**height`\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param height    Height of the Merkle Tree to construct\n     */\n    function calculateRoot(bytes32[] memory hashes, uint256 height) internal pure {\n        uint256 levelLength = hashes.length;\n        // Amount of hashes could not exceed amount of leafs in tree with the given height\n        if (levelLength \u003e (1 \u003c\u003c height)) revert TreeHeightTooLow();\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\": the amount of iterations for the for loop above.\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n            }\n        }\n    }\n\n    /**\n     * @notice Generates a proof of inclusion of a leaf in the list. If the requested index is outside\n     * of the list range, generates a proof of inclusion for an empty leaf (proof of non-inclusion).\n     * The Merkle Tree is constructed by padding the list with ZERO values until list length is a power of two\n     * __AND__ index is in the extended list range. For example:\n     *  - `hashes.length == 6` and `0 \u003c= index \u003c= 7` will \"extend\" the list to 8 entries.\n     *  - `hashes.length == 6` and `7 \u003c index \u003c= 15` will \"extend\" the list to 16 entries.\n     * \u003e Note: `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * Caller is expected not to reuse `hashes` list after the call.\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param index     Leaf index to generate the proof for\n     * @return proof    Generated merkle proof\n     */\n    function calculateProof(bytes32[] memory hashes, uint256 index) internal pure returns (bytes32[] memory proof) {\n        // Use only meaningful values for the shortened proof\n        // Check if index is within the list range (we want to generates proofs for outside leafs as well)\n        uint256 height = getHeight(index \u003c hashes.length ? hashes.length : (index + 1));\n        proof = new bytes32[](height);\n        uint256 levelLength = hashes.length;\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Use sibling for the merkle proof; `index^1` is index of our sibling\n                proof[h] = (index ^ 1 \u003c levelLength) ? hashes[index ^ 1] : bytes32(0);\n\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\"\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n                // Traverse to parent node\n                index \u003e\u003e= 1;\n            }\n        }\n    }\n\n    /// @notice Returns the height of the tree having a given amount of leafs.\n    function getHeight(uint256 leafs) internal pure returns (uint256 height) {\n        uint256 amount = 1;\n        while (amount \u003c leafs) {\n            unchecked {\n                ++height;\n            }\n            amount \u003c\u003c= 1;\n        }\n    }\n}\n\n// contracts/libs/stack/GasData.sol\n\n/// GasData in encoded data with \"basic information about gas prices\" for some chain.\ntype GasData is uint96;\n\nusing GasDataLib for GasData global;\n\n/// ChainGas is encoded data with given chain's \"basic information about gas prices\".\ntype ChainGas is uint128;\n\nusing GasDataLib for ChainGas global;\n\n/// Library for encoding and decoding GasData and ChainGas structs.\n/// # GasData\n/// `GasData` is a struct to store the \"basic information about gas prices\", that could\n/// be later used to approximate the cost of a message execution, and thus derive the\n/// minimal tip values for sending a message to the chain.\n/// \u003e - `GasData` is supposed to be cached by `GasOracle` contract, allowing to store the\n/// \u003e approximates instead of the exact values, and thus save on storage costs.\n/// \u003e - For instance, if `GasOracle` only updates the values on +- 10% change, having an\n/// \u003e 0.4% error on the approximates would be acceptable.\n/// `GasData` is supposed to be included in the Origin's state, which are synced across\n/// chains using Agent-signed snapshots and attestations.\n/// ## GasData stack layout (from highest bits to lowest)\n///\n/// | Position   | Field        | Type   | Bytes | Description                                         |\n/// | ---------- | ------------ | ------ | ----- | --------------------------------------------------- |\n/// | (012..010] | gasPrice     | uint16 | 2     | Gas price for the chain (in Wei per gas unit)       |\n/// | (010..008] | dataPrice    | uint16 | 2     | Calldata price (in Wei per byte of content)         |\n/// | (008..006] | execBuffer   | uint16 | 2     | Tx fee safety buffer for message execution (in Wei) |\n/// | (006..004] | amortAttCost | uint16 | 2     | Amortized cost for attestation submission (in Wei)  |\n/// | (004..002] | etherPrice   | uint16 | 2     | Chain's Ether Price / Mainnet Ether Price (in BWAD) |\n/// | (002..000] | markup       | uint16 | 2     | Markup for the message execution (in BWAD)          |\n/// \u003e See Number.sol for more details on `Number` type and BWAD (binary WAD) math.\n///\n/// ## ChainGas stack layout (from highest bits to lowest)\n///\n/// | Position   | Field   | Type   | Bytes | Description      |\n/// | ---------- | ------- | ------ | ----- | ---------------- |\n/// | (016..004] | gasData | uint96 | 12    | Chain's gas data |\n/// | (004..000] | domain  | uint32 | 4     | Chain's domain   |\nlibrary GasDataLib {\n    /// @dev Amount of bits to shift to gasPrice field\n    uint96 private constant SHIFT_GAS_PRICE = 10 * 8;\n    /// @dev Amount of bits to shift to dataPrice field\n    uint96 private constant SHIFT_DATA_PRICE = 8 * 8;\n    /// @dev Amount of bits to shift to execBuffer field\n    uint96 private constant SHIFT_EXEC_BUFFER = 6 * 8;\n    /// @dev Amount of bits to shift to amortAttCost field\n    uint96 private constant SHIFT_AMORT_ATT_COST = 4 * 8;\n    /// @dev Amount of bits to shift to etherPrice field\n    uint96 private constant SHIFT_ETHER_PRICE = 2 * 8;\n\n    /// @dev Amount of bits to shift to gasData field\n    uint128 private constant SHIFT_GAS_DATA = 4 * 8;\n\n    // ═════════════════════════════════════════════════ GAS DATA ══════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded GasData struct with the given fields.\n    /// @param gasPrice_        Gas price for the chain (in Wei per gas unit)\n    /// @param dataPrice_       Calldata price (in Wei per byte of content)\n    /// @param execBuffer_      Tx fee safety buffer for message execution (in Wei)\n    /// @param amortAttCost_    Amortized cost for attestation submission (in Wei)\n    /// @param etherPrice_      Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n    /// @param markup_          Markup for the message execution (in BWAD)\n    function encodeGasData(\n        Number gasPrice_,\n        Number dataPrice_,\n        Number execBuffer_,\n        Number amortAttCost_,\n        Number etherPrice_,\n        Number markup_\n    ) internal pure returns (GasData) {\n        // Number type wraps uint16, so could safely be casted to uint96\n        // forgefmt: disable-next-item\n        return GasData.wrap(\n            uint96(Number.unwrap(gasPrice_)) \u003c\u003c SHIFT_GAS_PRICE |\n            uint96(Number.unwrap(dataPrice_)) \u003c\u003c SHIFT_DATA_PRICE |\n            uint96(Number.unwrap(execBuffer_)) \u003c\u003c SHIFT_EXEC_BUFFER |\n            uint96(Number.unwrap(amortAttCost_)) \u003c\u003c SHIFT_AMORT_ATT_COST |\n            uint96(Number.unwrap(etherPrice_)) \u003c\u003c SHIFT_ETHER_PRICE |\n            uint96(Number.unwrap(markup_))\n        );\n    }\n\n    /// @notice Wraps padded uint256 value into GasData struct.\n    function wrapGasData(uint256 paddedGasData) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(paddedGasData));\n    }\n\n    /// @notice Returns the gas price, in Wei per gas unit.\n    function gasPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_GAS_PRICE));\n    }\n\n    /// @notice Returns the calldata price, in Wei per byte of content.\n    function dataPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_DATA_PRICE));\n    }\n\n    /// @notice Returns the tx fee safety buffer for message execution, in Wei.\n    function execBuffer(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_EXEC_BUFFER));\n    }\n\n    /// @notice Returns the amortized cost for attestation submission, in Wei.\n    function amortAttCost(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_AMORT_ATT_COST));\n    }\n\n    /// @notice Returns the ratio of Chain's Ether Price / Mainnet Ether Price, in BWAD math.\n    function etherPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_ETHER_PRICE));\n    }\n\n    /// @notice Returns the markup for the message execution, in BWAD math.\n    function markup(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data)));\n    }\n\n    // ════════════════════════════════════════════════ CHAIN DATA ═════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded ChainGas struct with the given fields.\n    /// @param gasData_ Chain's gas data\n    /// @param domain_  Chain's domain\n    function encodeChainGas(GasData gasData_, uint32 domain_) internal pure returns (ChainGas) {\n        // GasData type wraps uint96, so could safely be casted to uint128\n        return ChainGas.wrap(uint128(GasData.unwrap(gasData_)) \u003c\u003c SHIFT_GAS_DATA | uint128(domain_));\n    }\n\n    /// @notice Wraps padded uint256 value into ChainGas struct.\n    function wrapChainGas(uint256 paddedChainGas) internal pure returns (ChainGas) {\n        // Casting to uint128 will truncate the highest bits, which is the behavior we want\n        return ChainGas.wrap(uint128(paddedChainGas));\n    }\n\n    /// @notice Returns the chain's gas data.\n    function gasData(ChainGas data) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(ChainGas.unwrap(data) \u003e\u003e SHIFT_GAS_DATA));\n    }\n\n    /// @notice Returns the chain's domain.\n    function domain(ChainGas data) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(ChainGas.unwrap(data));\n    }\n\n    /// @notice Returns the hash for the list of ChainGas structs.\n    function snapGasHash(ChainGas[] memory snapGas) internal pure returns (bytes32 snapGasHash_) {\n        // Use assembly to calculate the hash of the array without copying it\n        // ChainGas takes a single word of storage, thus ChainGas[] is stored in the following way:\n        // 0x00: length of the array, in words\n        // 0x20: first ChainGas struct\n        // 0x40: second ChainGas struct\n        // And so on...\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Find the location where the array data starts, we add 0x20 to skip the length field\n            let loc := add(snapGas, 0x20)\n            // Load the length of the array (in words).\n            // Shifting left 5 bits is equivalent to multiplying by 32: this converts from words to bytes.\n            let len := shl(5, mload(snapGas))\n            // Calculate the hash of the array\n            snapGasHash_ := keccak256(loc, len)\n        }\n    }\n}\n\n// contracts/libs/stack/Header.sol\n\n/// Header is encoded data with \"general routing information\".\ntype Header is uint136;\n\nusing HeaderLib for Header global;\n\n/// Types of messages supported by Origin-Destination\n/// - Base: message sent by protocol user, contains tips\n/// - Manager: message sent between AgentManager contracts located on different chains, no tips\nenum MessageFlag {\n    Base,\n    Manager\n}\n\nusing HeaderLib for MessageFlag global;\n\n/// Library for formatting _the header part_ of _the messages used by Origin and Destination_.\n/// - Header represents general information for routing a Message for Origin and Destination.\n/// - Header occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n///\n/// # Header stack layout (from highest bits to lowest)\n///\n/// | Position   | Field            | Type   | Bytes | Description                             |\n/// | ---------- | ---------------- | ------ | ----- | --------------------------------------- |\n/// | (017..016] | flag             | uint8  | 1     | Flag specifying the type of message     |\n/// | (016..012] | origin           | uint32 | 4     | Domain where message originated         |\n/// | (012..008] | nonce            | uint32 | 4     | Message nonce on the origin domain      |\n/// | (008..004] | destination      | uint32 | 4     | Domain where message will be executed   |\n/// | (004..000] | optimisticPeriod | uint32 | 4     | Optimistic period that will be enforced |\nlibrary HeaderLib {\n    /// @dev Amount of bits to shift to flag field\n    uint136 private constant SHIFT_FLAG = 16 * 8;\n    /// @dev Amount of bits to shift to origin field\n    uint136 private constant SHIFT_ORIGIN = 12 * 8;\n    /// @dev Amount of bits to shift to nonce field\n    uint136 private constant SHIFT_NONCE = 8 * 8;\n    /// @dev Amount of bits to shift to destination field\n    uint136 private constant SHIFT_DESTINATION = 4 * 8;\n\n    /// @notice Returns an encoded header with provided fields\n    /// @param origin_              Domain of origin chain\n    /// @param nonce_               Message nonce on origin chain\n    /// @param destination_         Domain of destination chain\n    /// @param optimisticPeriod_    Optimistic period for message execution\n    function encodeHeader(\n        MessageFlag flag_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint32 destination_,\n        uint32 optimisticPeriod_\n    ) internal pure returns (Header) {\n        // All casts below are upcasts, so they are safe\n        // forgefmt: disable-next-item\n        return Header.wrap(\n            uint136(uint8(flag_)) \u003c\u003c SHIFT_FLAG |\n            uint136(origin_) \u003c\u003c SHIFT_ORIGIN |\n            uint136(nonce_) \u003c\u003c SHIFT_NONCE |\n            uint136(destination_) \u003c\u003c SHIFT_DESTINATION |\n            uint136(optimisticPeriod_)\n        );\n    }\n\n    /// @notice Checks that the header is a valid encoded header.\n    function isHeader(uint256 paddedHeader) internal pure returns (bool) {\n        // Check that flag is within range\n        return _flag(paddedHeader) \u003c= uint8(type(MessageFlag).max);\n    }\n\n    /// @notice Wraps the padded encoded request into a Header-typed value.\n    /// @dev The \"padded\" header is simply an encoded header casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded headers\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedHeader) internal pure returns (Header) {\n        // Check that flag is within range\n        if (!isHeader(paddedHeader)) revert FlagOutOfRange();\n        // Casting to uint136 will truncate the highest bits, which is the behavior we want\n        return Header.wrap(uint136(paddedHeader));\n    }\n\n    /// @notice Returns header's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Header header) internal pure returns (bytes32 hashedHeader) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store header in scratch space\n            mstore(0, header)\n            // Compute hash of header padded to 32 bytes\n            hashedHeader := keccak256(0, 32)\n        }\n    }\n\n    // ══════════════════════════════════════════════ HEADER SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns header's flag field\n    function flag(Header header) internal pure returns (MessageFlag) {\n        // We check that flag is within range when wrapping the header, so this cast is safe\n        return MessageFlag(_flag(Header.unwrap(header)));\n    }\n\n    /// @notice Returns header's origin field\n    function origin(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_ORIGIN);\n    }\n\n    /// @notice Returns header's nonce field\n    function nonce(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_NONCE);\n    }\n\n    /// @notice Returns header's destination field\n    function destination(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_DESTINATION);\n    }\n\n    /// @notice Returns header's optimistic seconds field\n    function optimisticPeriod(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns header's flag field without casting to MessageFlag\n    function _flag(uint256 paddedHeader) private pure returns (uint8) {\n        // Casting to uint8 will truncate the highest bits, which is the behavior we want\n        return uint8(paddedHeader \u003e\u003e SHIFT_FLAG);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n     * constructor.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall \u0026\u0026 _initialized \u003c 1) || (!AddressUpgradeable.isContract(address(this)) \u0026\u0026 _initialized == 1),\n            \"Initializable: contract is already initialized\"\n        );\n        _initialized = 1;\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: setting the version to 255 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing \u0026\u0026 _initialized \u003c version, \"Initializable: contract is already initialized\");\n        _initialized = version;\n        _initializing = true;\n        _;\n        _initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        require(_initializing, \"Initializable: contract is not initializing\");\n        _;\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized != type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint8) {\n        return _initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _initializing;\n    }\n}\n\n// contracts/interfaces/IAgentManager.sol\n\ninterface IAgentManager {\n    /**\n     * @notice Allows Inbox to open a Dispute between a Guard and a Notary, if they are both not in Dispute already.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Guard or Notary is already in Dispute.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Allows Inbox to slash an agent, if their fraud was proven.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Domain doesn't match the saved agent domain.\n     * @param domain    Domain where the Agent is active\n     * @param agent     Address of the Agent\n     * @param prover    Address that initially provided fraud proof\n     */\n    function slashAgent(uint32 domain, address agent, address prover) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest known root of the Agent Merkle Tree.\n     */\n    function agentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns the number of opened Disputes.\n     * @dev This includes the Disputes that have been resolved already.\n     */\n    function getDisputesAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns information about the dispute with the given index.\n     * @dev Will revert if dispute with given index hasn't been opened yet.\n     * @param index             Dispute index\n     * @return guard            Address of the Guard in the Dispute\n     * @return notary           Address of the Notary in the Dispute\n     * @return slashedAgent     Address of the Agent who was slashed when Dispute was resolved\n     * @return fraudProver      Address who provided fraud proof to resolve the Dispute\n     * @return reportPayload    Raw payload with report data that led to the Dispute\n     * @return reportSignature  Guard signature for the report payload\n     */\n    function getDispute(uint256 index)\n        external\n        view\n        returns (\n            address guard,\n            address notary,\n            address slashedAgent,\n            address fraudProver,\n            bytes memory reportPayload,\n            bytes memory reportSignature\n        );\n\n    /**\n     * @notice Returns the current Dispute status of a given agent. See Structures.sol for details.\n     * @dev Every returned value will be set to zero if agent was not slashed and is not in Dispute.\n     * `rival` and `disputePtr` will be set to zero if the agent was slashed without being in Dispute.\n     * @param agent         Agent address\n     * @return flag         Flag describing the current Dispute status for the agent: None/Pending/Slashed\n     * @return rival        Address of the rival agent in the Dispute\n     * @return fraudProver  Address who provided fraud proof to resolve the Dispute\n     * @return disputePtr   Index of the opened Dispute PLUS ONE. Zero if agent is not in Dispute.\n     */\n    function disputeStatus(address agent)\n        external\n        view\n        returns (DisputeFlag flag, address rival, address fraudProver, uint256 disputePtr);\n}\n\n// contracts/interfaces/IAgentSecured.sol\n\ninterface IAgentSecured {\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * between a Guard and a Notary has been opened.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * has been resolved due to one of the agents being slashed.\n     * \u003e `rivalIndex` will be ZERO, if the slashed agent was not in the Dispute.\n     * @param slashedIndex  Index of the slashed agent in the Agent Merkle Tree\n     * @param rivalIndex    Index of the their Dispute Rival in the Agent Merkle Tree\n     */\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the address of the local AgentManager contract, which is treated as\n     * the \"source of truth\" for agent statuses.\n     */\n    function agentManager() external view returns (address);\n\n    /**\n     * @notice Returns the address of the local Inbox contract, which is treated as\n     * the \"source of truth\" for agent-signed statements.\n     * @dev Inbox passes verified agent statements to `IAgentSecured` contract.\n     */\n    function inbox() external view returns (address);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns (flag, openedAt, resolvedAt) that describes the latest status of\n     * the latest dispute for an agent with a given index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param agentIndex    Agent index in the Agent Merkle Tree\n     * @return              Latest dispute status for the given agent: (flag, openedAt, resolvedAt)\n     */\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory);\n}\n\n// contracts/libs/memory/ByteString.sol\n\n/// @dev CallData is a memory view over the payload to be used for an external call, i.e.\n/// recipient.call(callData). Its length is always (4 + 32 * N) bytes:\n/// - First 4 bytes represent the function selector.\n/// - 32 * N bytes represent N words that function arguments occupy.\ntype CallData is uint256;\n\n/// @dev Attach library functions to CallData\nusing ByteString for CallData global;\n\n/// @dev Signature is a memory view over a \"65 bytes\" array representing a ECDSA signature.\ntype Signature is uint256;\n\n/// @dev Attach library functions to Signature\nusing ByteString for Signature global;\n\nlibrary ByteString {\n    using MemViewLib for bytes;\n\n    /**\n     * @dev non-compact ECDSA signatures are enforced as of OZ 4.7.3\n     *\n     *      Signature payload memory layout\n     * [000 .. 032) r   bytes32 32 bytes\n     * [032 .. 064) s   bytes32 32 bytes\n     * [064 .. 065) v   uint8    1 byte\n     */\n    uint256 internal constant SIGNATURE_LENGTH = 65;\n    uint256 private constant OFFSET_R = 0;\n    uint256 private constant OFFSET_S = 32;\n    uint256 private constant OFFSET_V = 64;\n\n    /**\n     * @dev Calldata memory layout\n     * [000 .. 004) selector    bytes4  4 bytes\n     *      Optional: N function arguments\n     * [004 .. 036) arg1        bytes32 32 bytes\n     *      ..\n     * [AAA .. END) argN        bytes32 32 bytes\n     */\n    uint256 internal constant SELECTOR_LENGTH = 4;\n    uint256 private constant OFFSET_SELECTOR = 0;\n    uint256 private constant OFFSET_ARGUMENTS = SELECTOR_LENGTH;\n\n    // ═════════════════════════════════════════════════ SIGNATURE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the signature payload from the given values.\n     * @dev Using ByteString.formatSignature({r: r, s: s, v: v}) will make sure\n     * that params are given in the right order.\n     */\n    function formatSignature(bytes32 r, bytes32 s, uint8 v) internal pure returns (bytes memory) {\n        return abi.encodePacked(r, s, v);\n    }\n\n    /**\n     * @notice Returns a Signature view over for the given payload.\n     * @dev Will revert if the payload is not a signature.\n     */\n    function castToSignature(bytes memory payload) internal pure returns (Signature) {\n        return castToSignature(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Signature view.\n     * @dev Will revert if the memory view is not over a signature.\n     */\n    function castToSignature(MemView memView) internal pure returns (Signature) {\n        if (!isSignature(memView)) revert UnformattedSignature();\n        return Signature.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a signature\n     */\n    function isSignature(MemView memView) internal pure returns (bool) {\n        return memView.len() == SIGNATURE_LENGTH;\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Signature signature) internal pure returns (MemView) {\n        return MemView.wrap(Signature.unwrap(signature));\n    }\n\n    // ═════════════════════════════════════════════ SIGNATURE SLICING ═════════════════════════════════════════════════\n\n    /// @notice Unpacks signature payload into (r, s, v) parameters.\n    /// @dev Make sure to verify signature length with isSignature() beforehand.\n    function toRSV(Signature signature) internal pure returns (bytes32 r, bytes32 s, uint8 v) {\n        // Get the underlying memory view\n        MemView memView = unwrap(signature);\n        r = memView.index({index_: OFFSET_R, bytes_: 32});\n        s = memView.index({index_: OFFSET_S, bytes_: 32});\n        // Can be safely casted to uint8, since we index a single byte\n        v = uint8(memView.indexUint({index_: OFFSET_V, bytes_: 1}));\n    }\n\n    // ═════════════════════════════════════════════════ CALLDATA ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the calldata with the modified arguments:\n     * the existing arguments are prepended with the arguments from the prefix.\n     * @dev Given:\n     *  - `calldata = abi.encodeWithSelector(foo.selector, d, e);`\n     *  - `prefix = abi.encode(a, b, c);`\n     *  - `a`, `b`, `c` are arguments of static type (i.e. not dynamically sized ones)\n     *      Then:\n     *  - Function will return abi.encodeWithSelector(foo.selector, a, c, c, d, e)\n     *  - Returned calldata will trigger `foo(a, b, c, d, e)` when used for a contract call.\n     * Note: for clarification as to what types are considered static, see\n     * https://docs.soliditylang.org/en/latest/abi-spec.html#formal-specification-of-the-encoding\n     * @param callData  Calldata that needs to be modified\n     * @param prefix    ABI-encoded arguments to use as the first arguments in the new calldata\n     * @return Modified calldata having prefix as the first arguments.\n     */\n    function addPrefix(CallData callData, bytes memory prefix) internal view returns (bytes memory) {\n        // Prefix should occupy a whole amount of words in memory\n        if (!_fullWords(prefix.length)) revert UnformattedCallDataPrefix();\n        MemView[] memory views = new MemView[](3);\n        // Use payload's function selector\n        views[0] = abi.encodePacked(callData.callSelector()).ref();\n        // Use prefix as the first arguments\n        views[1] = prefix.ref();\n        // Use payload's remaining arguments\n        views[2] = callData.arguments();\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a CallData view over for the given payload.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(bytes memory payload) internal pure returns (CallData) {\n        return castToCallData(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a CallData view.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(MemView memView) internal pure returns (CallData) {\n        if (!isCallData(memView)) revert UnformattedCallData();\n        return CallData.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a valid calldata, i.e.\n     * a function selector, followed by arbitrary amount of arguments.\n     */\n    function isCallData(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Calldata should at least have a function selector\n        if (length \u003c SELECTOR_LENGTH) return false;\n        // The remainder of the calldata should be exactly N memory words (N \u003e= 0)\n        return _fullWords(length - SELECTOR_LENGTH);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(CallData callData) internal pure returns (MemView) {\n        return MemView.wrap(CallData.unwrap(callData));\n    }\n\n    /// @notice Returns callData's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(CallData callData) internal pure returns (bytes32) {\n        return callData.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ CALLDATA SLICING ══════════════════════════════════════════════════\n\n    /**\n     * @notice Returns amount of memory words (32 byte chunks) the function arguments\n     * occupy in the calldata.\n     * @dev This might differ from amount of arguments supplied, if any of the arguments\n     * occupies more than one memory slot. It is true, however, that argument part of the payload\n     * occupies exactly N words, even for dynamic types like `bytes`\n     */\n    function argumentWords(CallData callData) internal pure returns (uint256) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        // Equivalent of (length - SELECTOR_LENGTH) / 32\n        return (memView.len() - SELECTOR_LENGTH) \u003e\u003e 5;\n    }\n\n    /// @notice Returns selector for the provided calldata.\n    function callSelector(CallData callData) internal pure returns (bytes4) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return bytes4(memView.index({index_: OFFSET_SELECTOR, bytes_: SELECTOR_LENGTH}));\n    }\n\n    /// @notice Returns abi encoded arguments for the provided calldata.\n    function arguments(CallData callData) internal pure returns (MemView) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return memView.sliceFrom({index_: OFFSET_ARGUMENTS});\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if length is full amount of memory words (32 bytes).\n    function _fullWords(uint256 length) internal pure returns (bool) {\n        // The equivalent of length % 32 == 0\n        return length \u0026 31 == 0;\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n    function __Context_init() internal onlyInitializing {\n    }\n\n    function __Context_init_unchained() internal onlyInitializing {\n    }\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[50] private __gap;\n}\n\n// contracts/libs/merkle/MerkleTree.sol\n\n/// `BaseTree` is a struct representing incremental merkle tree.\n/// - Contains only the current branch.\n/// - The number of inserted leaves is stored externally, and is later supplied for tree operations.\n/// - Has a fixed height of `ORIGIN_TREE_HEIGHT`.\n/// - Can store up to `2 ** ORIGIN_TREE_HEIGHT - 1` leaves.\n/// \u003e Note: the hash function for the tree `H(x, y)` is defined as:\n/// \u003e - `H(0,0) = 0`\n/// \u003e - `H(x,y) = keccak256(x, y), when (x != 0 || y != 0)`\n/// ## Invariant for leafs\n/// - The leftmost empty leaf has `index == count`, where `count` is the amount of the inserted leafs so far.\n/// - Value for any empty leaf or node is bytes32(0).\n/// ## Invariant for current branch\n/// `branch[i]` is always the value of a node on the i-th level.\n/// Levels are numbered from leafs to root: `0 .. ORIGIN_TREE_HEIGHT`.\n/// `branch[i]` stores the value for the node, such that:\n//  - The node is a \"left child\" (e.g. has an even index).\n/// - The node must have two non-empty children.\n/// - Out of all level's \"left child\" nodes with \"non-empty children\",\n/// the one with the biggest index (the rightmost one) is stored as `branch[i]`.\n/// \u003e __`branch` could be used to form a proof of inclusion for the first empty leaf (`index == count`).__\n/// _Here is how:_\n/// - Let's walk along the path from the \"first empty leaf\" to the root.\n/// - i-th bit of the \"first empty leaf\" index (which is equal to `count`) determines if the path's node\n/// for this i-th level is a \"left child\" or a \"right child\".\n/// - i-th bit in `count` is 0 → we are the left child on this level → sibling is the right child\n/// that does not exist yet → `proof[i] = bytes32(0)`.\n/// - i-th bit in `count` is 1 → we are the right child on this level → sibling is the left child\n/// sibling is the rightmost \"left child\" node on the level → `proof[i] = branch[i]`.\n/// \u003e Therefore `proof[i] = (count \u0026 (1 \u003c\u003c i)) == 0 ? bytes32(0) : branch[i])`\nstruct BaseTree {\n    bytes32[ORIGIN_TREE_HEIGHT] branch;\n}\n\nusing MerkleTree for BaseTree global;\n\n/// `HistoricalTree` is an incremental merkle tree keeping track of its historical merkle roots.\n/// \u003e - `roots[N]` is the root of the tree after `N` leafs were inserted\n/// \u003e - `roots[0] == bytes32(0)`\n/// @param tree     Incremental merkle tree\n/// @param roots    Historical merkle roots of the tree\nstruct HistoricalTree {\n    BaseTree tree;\n    bytes32[] roots;\n}\n\nusing MerkleTree for HistoricalTree global;\n\n/// `DynamicTree` is a struct representing a Merkle Tree with `2**AGENT_TREE_HEIGHT` leaves.\n/// - A single operation is available: update value for leaf with an arbitrary index (which might be a non-empty leaf).\n/// - This is done by requesting the proof of inclusion for the old value, which is used to both\n/// verify the old value, and calculate the new root.\n/// \u003e Based on Original idea from [ER forum post](https://ethresear.ch/t/efficient-on-chain-dynamic-merkle-tree/11054).\nstruct DynamicTree {\n    bytes32 root;\n}\n\nusing MerkleTree for DynamicTree global;\n\n/// MerkleTree is work based on Nomad's Merkle.sol, which is used under MIT OR Apache-2.0\n/// [link](https://github.com/nomad-xyz/monorepo/blob/main/packages/contracts-core/contracts/libs/Merkle.sol).\n/// With the following changes:\n/// - Adapted for Solidity 0.8.x.\n/// - Amount of tree leaves stored externally.\n/// - Added thorough documentation.\n/// - `H(0,0) = 0` optimization from [ER forum post](https://ethresear.ch/t/optimizing-sparse-merkle-trees/3751/6).\n/// \u003e Nomad's Merkle.sol is work based on eth2 deposit contract, which is used under CC0-1.0\n///[link](https://github.com/ethereum/deposit_contract/blob/dev/deposit_contract/contracts/validator_registration.v.py).\n/// With the following changes:\n/// \u003e - Implemented in Solidity 0.7.6 (eth2 deposit contract implemented in Vyper).\n/// \u003e - `H() = keccak256()` is used as the hashing function instead of `sha256()`.\nlibrary MerkleTree {\n    /// @dev For root calculation we need at least one empty leaf, thus the minus one in the formula.\n    uint256 internal constant MAX_LEAVES = 2 ** ORIGIN_TREE_HEIGHT - 1;\n\n    // ═════════════════════════════════════════════════ BASE TREE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Inserts `node` into merkle tree\n     * @dev Reverts if tree is full\n     * @param newCount  Amount of inserted leaves in the tree after the insertion (i.e. current + 1)\n     * @param node      Element to insert into tree\n     */\n    function insertBase(BaseTree storage tree, uint256 newCount, bytes32 node) internal {\n        if (newCount \u003e MAX_LEAVES) revert MerkleTreeFull();\n        // We go up the tree following the branch from the empty leaf AFTER the just inserted one.\n        // We stop when we find the first \"right child\" node.\n        // Its sibling is now the rightmost \"left child\" node that has two non-empty children.\n        // Therefore we need to update `tree.branch` value on this level.\n        // One could see that `tree.branch` value on lower and higher levels remain unchanged.\n\n        // Loop invariant: `node` is the current level's value for the branch from JUST INSERTED leaf\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            if ((newCount \u0026 1) == 1) {\n                // Found the first \"right child\" node on the branch from EMPTY leaf\n                // `node` is the value for node on branch from JUST INSERTED leaf\n                // Which in this case is the \"left child\".\n                // We update tree.branch and exit\n                tree.branch[i] = node;\n                return;\n            }\n            // On the branch from EMPTY leaf this is still a \"left child\".\n            // Meaning on branch from JUST INSERTED leaf, `node` is a right child.\n            // We compute value for `node` parent using `tree.branch` invariant:\n            // This is the rightmost \"left child\" node, which would be sibling of `node`.\n            node = MerkleMath.getParent(tree.branch[i], node);\n            // Get the parent index, and go to the next tree level\n            newCount \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n        // As the loop should always end prematurely with the `return` statement,\n        // this code should be unreachable. We assert `false` just to be safe.\n        assert(false);\n    }\n\n    /**\n     * @notice Calculates and returns current root of the merkle tree.\n     * @param count     Current amount of inserted leaves in the tree\n     * @return current  Calculated root of `tree`\n     */\n    function rootBase(BaseTree storage tree, uint256 count) internal view returns (bytes32 current) {\n        // To calculate the root we follow the branch of first EMPTY leaf (index == count)\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            // Check if we are the left or the right child on the current level\n            if ((count \u0026 1) == 1) {\n                // We are the right child. Our sibling is the \"rightmost\" \"left-child\" node\n                // that has two non-empty children → sibling is `tree.branch[i]`\n                current = MerkleMath.getParent(tree.branch[i], current);\n            } else {\n                // We are the left child. Our sibling does not exist yet → sibling is EMPTY\n                current = MerkleMath.getParent(current, bytes32(0));\n            }\n            // Get the parent index, and go to the next tree level\n            count \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    // ══════════════════════════════════════════════ HISTORICAL TREE ══════════════════════════════════════════════════\n\n    /// @notice Initializes the historical roots for the tree by inserting an empty root.\n    // solhint-disable-next-line ordering\n    function initializeRoots(HistoricalTree storage tree) internal returns (bytes32 savedRoot) {\n        // This should only be called once, when the contract is initialized\n        assert(tree.roots.length == 0);\n        // Save root for empty merkle tree: bytes32(0)\n        tree.roots.push(savedRoot);\n    }\n\n    /// @notice Inserts a new leaf into the merkle tree.\n    /// @dev Reverts if tree is full.\n    /// @param node         Element to insert into tree\n    /// @return newRoot     Merkle root after the leaf was inserted\n    function insert(HistoricalTree storage tree, bytes32 node) internal returns (bytes32 newRoot) {\n        // Tree count after the new leaf will be inserted (we store roots[0] as root of empty tree)\n        uint256 newCount = tree.roots.length;\n        tree.tree.insertBase(newCount, node);\n        // Save the new root\n        newRoot = tree.tree.rootBase(newCount);\n        tree.roots.push(newRoot);\n    }\n\n    /// @notice Returns the historical root of the merkle tree.\n    /// @dev Reverts if not enough leafs have been inserted.\n    /// @param count            Amount of leafs in the tree at some point of time\n    /// @return historicalRoot  Merkle root after `count` leafs were inserted\n    function root(HistoricalTree storage tree, uint256 count) internal view returns (bytes32 historicalRoot) {\n        if (count \u003e= tree.roots.length) revert NotEnoughLeafs();\n        return tree.roots[count];\n    }\n\n    // ═══════════════════════════════════════════════ DYNAMIC TREE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Updates the value for the leaf with the given index in the Dynamic Merkle Tree.\n     * @dev Will revert if incorrect proof of inclusion for old value is supplied.\n     * @param tree          Dynamic merkle tree\n     * @param index         Index of the leaf to update\n     * @param oldValue      Previous value of the leaf\n     * @param branch        Proof of inclusion of previous value into the tree\n     * @param newValue      New leaf value to assign\n     * @return newRoot      New value for the Merkle Root after the leaf is updated\n     */\n    function update(\n        DynamicTree storage tree,\n        uint256 index,\n        bytes32 oldValue,\n        bytes32[] memory branch,\n        bytes32 newValue\n    ) internal returns (bytes32 newRoot) {\n        // Check that the old value + proof result in a correct root\n        if (MerkleMath.proofRoot(index, oldValue, branch, AGENT_TREE_HEIGHT) != tree.root) {\n            revert LeafNotProven();\n        }\n        // New root is new value + the same proof (values for sibling nodes are not updated)\n        newRoot = MerkleMath.proofRoot(index, newValue, branch, AGENT_TREE_HEIGHT);\n        // Write the new root\n        tree.root = newRoot;\n    }\n}\n\n// contracts/libs/stack/Tips.sol\n\n/// Tips is encoded data with \"tips paid for sending a base message\".\n/// Note: even though uint256 is also an underlying type for MemView, Tips is stored ON STACK.\ntype Tips is uint256;\n\nusing TipsLib for Tips global;\n\n/// # Tips\n/// Library for formatting _the tips part_ of _the base messages_.\n///\n/// ## How the tips are awarded\n/// Tips are paid for sending a base message, and are split across all the agents that\n/// made the message execution on destination chain possible.\n/// ### Summit tips\n/// Split between:\n///     - Guard posting a snapshot with state ST_G for the origin chain.\n///     - Notary posting a snapshot SN_N using ST_G. This creates attestation A.\n///     - Notary posting a message receipt after it is executed on destination chain.\n/// ### Attestation tips\n/// Paid to:\n///     - Notary posting attestation A to destination chain.\n/// ### Execution tips\n/// Paid to:\n///     - First executor performing a valid execution attempt (correct proofs, optimistic period over),\n///      using attestation A to prove message inclusion on origin chain, whether the recipient reverted or not.\n/// ### Delivery tips.\n/// Paid to:\n///     - Executor who successfully executed the message on destination chain.\n///\n/// ## Tips encoding\n/// - Tips occupy a single storage word, and thus are stored on stack instead of being stored in memory.\n/// - The actual tip values should be determined by multiplying stored values by divided by TIPS_MULTIPLIER=2**32.\n/// - Tips are packed into a single word of storage, while allowing real values up to ~8*10**28 for every tip category.\n/// \u003e The only downside is that the \"real tip values\" are now multiplies of ~4*10**9, which should be fine even for\n/// the chains with the most expensive gas currency.\n/// # Tips stack layout (from highest bits to lowest)\n///\n/// | Position   | Field          | Type   | Bytes | Description                                                |\n/// | ---------- | -------------- | ------ | ----- | ---------------------------------------------------------- |\n/// | (032..024] | summitTip      | uint64 | 8     | Tip for agents interacting with Summit contract            |\n/// | (024..016] | attestationTip | uint64 | 8     | Tip for Notary posting attestation to Destination contract |\n/// | (016..008] | executionTip   | uint64 | 8     | Tip for valid execution attempt on destination chain       |\n/// | (008..000] | deliveryTip    | uint64 | 8     | Tip for successful message delivery on destination chain   |\n\nlibrary TipsLib {\n    using SafeCast for uint256;\n\n    /// @dev Amount of bits to shift to summitTip field\n    uint256 private constant SHIFT_SUMMIT_TIP = 24 * 8;\n    /// @dev Amount of bits to shift to attestationTip field\n    uint256 private constant SHIFT_ATTESTATION_TIP = 16 * 8;\n    /// @dev Amount of bits to shift to executionTip field\n    uint256 private constant SHIFT_EXECUTION_TIP = 8 * 8;\n\n    // ═══════════════════════════════════════════════════ TIPS ════════════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips with the given fields\n    /// @param summitTip_        Tip for agents interacting with Summit contract, divided by TIPS_MULTIPLIER\n    /// @param attestationTip_   Tip for Notary posting attestation to Destination contract, divided by TIPS_MULTIPLIER\n    /// @param executionTip_     Tip for valid execution attempt on destination chain, divided by TIPS_MULTIPLIER\n    /// @param deliveryTip_      Tip for successful message delivery on destination chain, divided by TIPS_MULTIPLIER\n    function encodeTips(uint64 summitTip_, uint64 attestationTip_, uint64 executionTip_, uint64 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // forgefmt: disable-next-item\n        return Tips.wrap(\n            uint256(summitTip_) \u003c\u003c SHIFT_SUMMIT_TIP |\n            uint256(attestationTip_) \u003c\u003c SHIFT_ATTESTATION_TIP |\n            uint256(executionTip_) \u003c\u003c SHIFT_EXECUTION_TIP |\n            uint256(deliveryTip_)\n        );\n    }\n\n    /// @notice Convenience function to encode tips with uint256 values.\n    function encodeTips256(uint256 summitTip_, uint256 attestationTip_, uint256 executionTip_, uint256 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // In practice, the tips amounts are not supposed to be higher than 2**96, and with 32 bits of granularity\n        // using uint64 is enough to store the values. However, we still check for overflow just in case.\n        // TODO: consider using Number type to store the tips values.\n        return encodeTips({\n            summitTip_: (summitTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            attestationTip_: (attestationTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            executionTip_: (executionTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            deliveryTip_: (deliveryTip_ \u003e\u003e TIPS_GRANULARITY).toUint64()\n        });\n    }\n\n    /// @notice Wraps the padded encoded tips into a Tips-typed value.\n    /// @dev There is no actual padding here, as the underlying type is already uint256,\n    /// but we include this function for consistency and to be future-proof, if tips will eventually use anything\n    /// smaller than uint256.\n    function wrapPadded(uint256 paddedTips) internal pure returns (Tips) {\n        return Tips.wrap(paddedTips);\n    }\n\n    /**\n     * @notice Returns a formatted Tips payload specifying empty tips.\n     * @return Formatted tips\n     */\n    function emptyTips() internal pure returns (Tips) {\n        return Tips.wrap(0);\n    }\n\n    /// @notice Returns tips's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Tips tips) internal pure returns (bytes32 hashedTips) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store tips in scratch space\n            mstore(0, tips)\n            // Compute hash of tips padded to 32 bytes\n            hashedTips := keccak256(0, 32)\n        }\n    }\n\n    // ═══════════════════════════════════════════════ TIPS SLICING ════════════════════════════════════════════════════\n\n    /// @notice Returns summitTip field\n    function summitTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_SUMMIT_TIP);\n    }\n\n    /// @notice Returns attestationTip field\n    function attestationTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_ATTESTATION_TIP);\n    }\n\n    /// @notice Returns executionTip field\n    function executionTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_EXECUTION_TIP);\n    }\n\n    /// @notice Returns deliveryTip field\n    function deliveryTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips));\n    }\n\n    // ════════════════════════════════════════════════ TIPS VALUE ═════════════════════════════════════════════════════\n\n    /// @notice Returns total value of the tips payload.\n    /// This is the sum of the encoded values, scaled up by TIPS_MULTIPLIER\n    function value(Tips tips) internal pure returns (uint256 value_) {\n        value_ = uint256(tips.summitTip()) + tips.attestationTip() + tips.executionTip() + tips.deliveryTip();\n        value_ \u003c\u003c= TIPS_GRANULARITY;\n    }\n\n    /// @notice Increases the delivery tip to match the new value.\n    function matchValue(Tips tips, uint256 newValue) internal pure returns (Tips newTips) {\n        uint256 oldValue = tips.value();\n        if (newValue \u003c oldValue) revert TipsValueTooLow();\n        // We want to increase the delivery tip, while keeping the other tips the same\n        unchecked {\n            uint256 delta = (newValue - oldValue) \u003e\u003e TIPS_GRANULARITY;\n            // `delta` fits into uint224, as TIPS_GRANULARITY is 32, so this never overflows uint256.\n            // In practice, this will never overflow uint64 as well, but we still check it just in case.\n            if (delta + tips.deliveryTip() \u003e type(uint64).max) revert TipsOverflow();\n            // Delivery tips occupy lowest 8 bytes, so we can just add delta to the tips value\n            // to effectively increase the delivery tip (knowing that delta fits into uint64).\n            newTips = Tips.wrap(Tips.unwrap(tips) + delta);\n        }\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    function __Ownable_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable_init_unchained() internal onlyInitializing {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n    function __Ownable2Step_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable2Step_init_unchained() internal onlyInitializing {\n    }\n    address private _pendingOwner;\n\n    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Returns the address of the pending owner.\n     */\n    function pendingOwner() public view virtual returns (address) {\n        return _pendingOwner;\n    }\n\n    /**\n     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual override onlyOwner {\n        _pendingOwner = newOwner;\n        emit OwnershipTransferStarted(owner(), newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual override {\n        delete _pendingOwner;\n        super._transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev The new owner accepts the ownership transfer.\n     */\n    function acceptOwnership() public virtual {\n        address sender = _msgSender();\n        require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n        _transferOwnership(sender);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// contracts/libs/memory/State.sol\n\n/// State is a memory view over a formatted state payload.\ntype State is uint256;\n\nusing StateLib for State global;\n\n/// # State\n/// State structure represents the state of Origin contract at some point of time.\n/// - State is structured in a way to track the updates of the Origin Merkle Tree.\n/// - State includes root of the Origin Merkle Tree, origin domain and some additional metadata.\n/// ## Origin Merkle Tree\n/// Hash of every sent message is inserted in the Origin Merkle Tree, which changes\n/// the value of Origin Merkle Root (which is the root for the mentioned tree).\n/// - Origin has a single Merkle Tree for all messages, regardless of their destination domain.\n/// - This leads to Origin state being updated if and only if a message was sent in a block.\n/// - Origin contract is a \"source of truth\" for states: a state is considered \"valid\" in its Origin,\n/// if it matches the state of the Origin contract after the N-th (nonce) message was sent.\n///\n/// # Memory layout of State fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                    |\n/// | ---------- | ----------- | ------- | ----- | ------------------------------ |\n/// | [000..032) | root        | bytes32 | 32    | Root of the Origin Merkle Tree |\n/// | [032..036) | origin      | uint32  | 4     | Domain where Origin is located |\n/// | [036..040) | nonce       | uint32  | 4     | Amount of sent messages        |\n/// | [040..045) | blockNumber | uint40  | 5     | Block of last sent message     |\n/// | [045..050) | timestamp   | uint40  | 5     | Time of last sent message      |\n/// | [050..062) | gasData     | uint96  | 12    | Gas data for the chain         |\n///\n/// @dev State could be used to form a Snapshot to be signed by a Guard or a Notary.\nlibrary StateLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_ROOT = 0;\n    uint256 private constant OFFSET_ORIGIN = 32;\n    uint256 private constant OFFSET_NONCE = 36;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 40;\n    uint256 private constant OFFSET_TIMESTAMP = 45;\n    uint256 private constant OFFSET_GAS_DATA = 50;\n\n    // ═══════════════════════════════════════════════════ STATE ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted State payload with provided fields\n     * @param root_         New merkle root\n     * @param origin_       Domain of Origin's chain\n     * @param nonce_        Nonce of the merkle root\n     * @param blockNumber_  Block number when root was saved in Origin\n     * @param timestamp_    Block timestamp when root was saved in Origin\n     * @param gasData_      Gas data for the chain\n     * @return Formatted state\n     */\n    function formatState(\n        bytes32 root_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_,\n        GasData gasData_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(root_, origin_, nonce_, blockNumber_, timestamp_, gasData_);\n    }\n\n    /**\n     * @notice Returns a State view over the given payload.\n     * @dev Will revert if the payload is not a state.\n     */\n    function castToState(bytes memory payload) internal pure returns (State) {\n        return castToState(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a State view.\n     * @dev Will revert if the memory view is not over a state.\n     */\n    function castToState(MemView memView) internal pure returns (State) {\n        if (!isState(memView)) revert UnformattedState();\n        return State.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted State.\n    function isState(MemView memView) internal pure returns (bool) {\n        return memView.len() == STATE_LENGTH;\n    }\n\n    /// @notice Returns the hash of a State, that could be later signed by a Guard to signal\n    /// that the state is invalid.\n    function hashInvalid(State state) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(stateInvalidSalt, keccak(state))\n        return state.unwrap().keccakSalted(STATE_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(State state) internal pure returns (MemView) {\n        return MemView.wrap(State.unwrap(state));\n    }\n\n    /// @notice Compares two State structures.\n    function equals(State a, State b) internal pure returns (bool) {\n        // Length of a State payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═══════════════════════════════════════════════ STATE HASHING ═══════════════════════════════════════════════════\n\n    /// @notice Returns the hash of the State.\n    /// @dev We are using the Merkle Root of a tree with two leafs (see below) as state hash.\n    function leaf(State state) internal pure returns (bytes32) {\n        (bytes32 leftLeaf_, bytes32 rightLeaf_) = state.subLeafs();\n        // Final hash is the parent of these leafs\n        return keccak256(bytes.concat(leftLeaf_, rightLeaf_));\n    }\n\n    /// @notice Returns \"sub-leafs\" of the State. Hash of these \"sub leafs\" is going to be used\n    /// as a \"state leaf\" in the \"Snapshot Merkle Tree\".\n    /// This enables proving that leftLeaf = (root, origin) was a part of the \"Snapshot Merkle Tree\",\n    /// by combining `rightLeaf` with the remainder of the \"Snapshot Merkle Proof\".\n    function subLeafs(State state) internal pure returns (bytes32 leftLeaf_, bytes32 rightLeaf_) {\n        MemView memView = state.unwrap();\n        // Left leaf is (root, origin)\n        leftLeaf_ = memView.prefix({len_: OFFSET_NONCE}).keccak();\n        // Right leaf is (metadata), or (nonce, blockNumber, timestamp)\n        rightLeaf_ = memView.sliceFrom({index_: OFFSET_NONCE}).keccak();\n    }\n\n    /// @notice Returns the left \"sub-leaf\" of the State.\n    function leftLeaf(bytes32 root_, uint32 origin_) internal pure returns (bytes32) {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(root_, origin_));\n    }\n\n    /// @notice Returns the right \"sub-leaf\" of the State.\n    function rightLeaf(uint32 nonce_, uint40 blockNumber_, uint40 timestamp_, GasData gasData_)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(nonce_, blockNumber_, timestamp_, gasData_));\n    }\n\n    // ═══════════════════════════════════════════════ STATE SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns a historical Merkle root from the Origin contract.\n    function root(State state) internal pure returns (bytes32) {\n        return state.unwrap().index({index_: OFFSET_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns domain of chain where the Origin contract is deployed.\n    function origin(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns nonce of Origin contract at the time, when `root` was the Merkle root.\n    function nonce(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when `root` was saved in Origin.\n    function blockNumber(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when `root` was saved in Origin.\n    /// @dev This is the timestamp according to the origin chain.\n    function timestamp(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n\n    /// @notice Returns gas data for the chain.\n    function gasData(State state) internal pure returns (GasData) {\n        return GasDataLib.wrapGasData(state.unwrap().indexUint({index_: OFFSET_GAS_DATA, bytes_: GAS_DATA_LENGTH}));\n    }\n}\n\n// contracts/libs/memory/BaseMessage.sol\n\n/// BaseMessage is a memory view over the base message supported by Origin-Destination\ntype BaseMessage is uint256;\n\nusing BaseMessageLib for BaseMessage global;\n\n/// BaseMessage structure represents a base message sent via the Origin-Destination contracts.\n/// - It only contains data relevant to the base message, the rest of data is encoded in the message header.\n/// - `sender` and `recipient` for EVM chains are EVM addresses casted to bytes32, while preserving left-alignment.\n/// - `tips` and `request` parameters are specified by a message sender\n/// \u003e Origin will calculate minimum tips for given request and content length, and will reject messages with tips\n/// lower than that.\n///\n/// # Memory layout of BaseMessage fields\n///\n/// | Position   | Field     | Type    | Bytes | Description                            |\n/// | ---------- | --------- | ------- | ----- | -------------------------------------- |\n/// | [000..032) | tips      | uint256 | 32    | Encoded tips paid on origin chain      |\n/// | [032..064) | sender    | bytes32 | 32    | Sender address on origin chain         |\n/// | [064..096) | recipient | bytes32 | 32    | Recipient address on destination chain |\n/// | [096..116) | request   | uint160 | 20    | Encoded request for message execution  |\n/// | [104..AAA) | content   | bytes   | ??    | Content to be passed to recipient      |\nlibrary BaseMessageLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_TIPS = 0;\n    uint256 private constant OFFSET_SENDER = 32;\n    uint256 private constant OFFSET_RECIPIENT = 64;\n    uint256 private constant OFFSET_REQUEST = OFFSET_RECIPIENT + TIPS_LENGTH;\n    uint256 private constant OFFSET_CONTENT = OFFSET_REQUEST + REQUEST_LENGTH;\n\n    // ═══════════════════════════════════════════════ BASE MESSAGE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted BaseMessage payload with provided fields.\n     * @param tips_         Encoded tips information\n     * @param sender_       Sender address on origin chain\n     * @param recipient_    Recipient address on destination chain\n     * @param request_      Encoded request for message execution\n     * @param content_      Raw content to be passed to recipient on destination chain\n     * @return Formatted base message\n     */\n    function formatBaseMessage(Tips tips_, bytes32 sender_, bytes32 recipient_, Request request_, bytes memory content_)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return abi.encodePacked(tips_, sender_, recipient_, request_, content_);\n    }\n\n    /**\n     * @notice Returns a BaseMessage view over the given payload.\n     * @dev Will revert if the payload is not a base message.\n     */\n    function castToBaseMessage(bytes memory payload) internal pure returns (BaseMessage) {\n        return castToBaseMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a BaseMessage view.\n     * @dev Will revert if the memory view is not over a base message payload.\n     */\n    function castToBaseMessage(MemView memView) internal pure returns (BaseMessage) {\n        if (!isBaseMessage(memView)) revert UnformattedBaseMessage();\n        return BaseMessage.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted BaseMessage.\n    function isBaseMessage(MemView memView) internal pure returns (bool) {\n        // Check if sender, recipient, tips fields exist\n        return (memView.len() \u003e= OFFSET_CONTENT);\n        // Content could be empty, so we don't check that\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(BaseMessage baseMessage) internal pure returns (MemView) {\n        return MemView.wrap(BaseMessage.unwrap(baseMessage));\n    }\n\n    /// @notice Returns baseMessage's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        // We hash \"tips\" and \"everything but tips\" to make tips proofs easier to verify\n        return MerkleMath.getParent(baseMessage.tips().leaf(), baseMessage.bodyLeaf());\n    }\n\n    /// @notice Returns hash for the \"everything but tips\" part of the base message.\n    function bodyLeaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_SENDER}).keccak();\n    }\n\n    // ═══════════════════════════════════════════ BASE MESSAGE SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips paid on origin chain.\n    function tips(BaseMessage baseMessage) internal pure returns (Tips) {\n        return TipsLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_TIPS, bytes_: TIPS_LENGTH})));\n    }\n\n    /// @notice Returns sender address on origin chain.\n    function sender(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_SENDER, bytes_: 32});\n    }\n\n    /// @notice Returns recipient address on destination chain.\n    function recipient(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_RECIPIENT, bytes_: 32});\n    }\n\n    /// @notice Returns an encoded request for message execution on destination chain.\n    function request(BaseMessage baseMessage) internal pure returns (Request) {\n        return RequestLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_REQUEST, bytes_: REQUEST_LENGTH})));\n    }\n\n    /// @notice Returns an untyped memory view over the content to be passed to recipient.\n    function content(BaseMessage baseMessage) internal pure returns (MemView) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_CONTENT});\n    }\n}\n\n// contracts/base/MessagingBase.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for all messaging contracts.\n * - Provides context on the local chain's domain.\n * - Provides ownership functionality.\n * - Will be providing pausing functionality when it is implemented.\n */\nabstract contract MessagingBase is MultiCallable, Versioned, Ownable2StepUpgradeable {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @notice Domain of the local chain, set once upon contract creation\n    uint32 public immutable localDomain;\n    // @notice Domain of the Synapse chain, set once upon contract creation\n    uint32 public immutable synapseDomain;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev gap for upgrade safety\n    uint256[50] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    constructor(string memory version_, uint32 synapseDomain_) Versioned(version_) {\n        localDomain = ChainContext.chainId();\n        synapseDomain = synapseDomain_;\n    }\n\n    // TODO: Implement pausing\n\n    /**\n     * @dev Should be impossible to renounce ownership;\n     * we override OpenZeppelin OwnableUpgradeable's\n     * implementation of renounceOwnership to make it a no-op\n     */\n    function renounceOwnership() public override onlyOwner {} //solhint-disable-line no-empty-blocks\n}\n\n// contracts/libs/memory/Message.sol\n\n/// Message is a memory over over a formatted message payload.\ntype Message is uint256;\n\nusing MessageLib for Message global;\n\n/// Library for formatting the various messages supported by Origin and Destination.\n///\n/// # Message memory layout\n///\n/// | Position   | Field  | Type    | Bytes | Description                                             |\n/// | ---------- | ------ | ------- | ----- | ------------------------------------------------------- |\n/// | [000..017) | header | uint136 | 17    | Encoded general routing information for the message     |\n/// | [017..AAA) | body   | bytes   | ??    | Formatted payload (according to flag) with message body |\nlibrary MessageLib {\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MemViewLib for bytes;\n    using HeaderLib for MemView;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_HEADER = 0;\n    uint256 private constant OFFSET_BODY = OFFSET_HEADER + HEADER_LENGTH;\n\n    // ══════════════════════════════════════════════════ MESSAGE ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns formatted message with provided fields.\n     * @param header_   Encoded general routing information for the message\n     * @param body_     Formatted payload (according to flag) with message body\n     * @return Formatted message\n     */\n    function formatMessage(Header header_, bytes memory body_) internal pure returns (bytes memory) {\n        return abi.encodePacked(header_, body_);\n    }\n\n    /**\n     * @notice Returns a Message view over for the given payload.\n     * @dev Will revert if the payload is not a message payload.\n     */\n    function castToMessage(bytes memory payload) internal pure returns (Message) {\n        return castToMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Message view.\n     * @dev Will revert if the memory view is not over a message payload.\n     */\n    function castToMessage(MemView memView) internal pure returns (Message) {\n        if (!isMessage(memView)) revert UnformattedMessage();\n        return Message.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Message.\n     */\n    function isMessage(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Check if headers exist in the payload\n        if (length \u003c OFFSET_BODY) return false;\n        // Check that Header is valid\n        uint256 paddedHeader = _header(memView);\n        if (!HeaderLib.isHeader(paddedHeader)) return false;\n        // Check that body is formatted according to the flag\n        // Only Base/Manager message flags exist\n        if (HeaderLib.wrapPadded(paddedHeader).flag() == MessageFlag.Base) {\n            // Check if body is a formatted base message\n            return _body(memView).isBaseMessage();\n        } else {\n            // Check if body is a formatted calldata for AgentManager call\n            return _body(memView).isCallData();\n        }\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Message message) internal pure returns (MemView) {\n        return MemView.wrap(Message.unwrap(message));\n    }\n\n    /// @notice Returns message's hash: a leaf to be inserted in the Merkle tree.\n    function leaf(Message message) internal pure returns (bytes32) {\n        // We hash header and body separately to make message proofs easier to verify\n        Header header_ = message.header();\n        // Only Base/Manager message flags exist\n        if (header_.flag() == MessageFlag.Base) {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToBaseMessage().leaf());\n        } else {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToCallData().leaf());\n        }\n    }\n\n    // ══════════════════════════════════════════════ MESSAGE SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns message's encoded header field.\n    function header(Message message) internal pure returns (Header) {\n        return HeaderLib.wrapPadded((message.unwrap().indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH})));\n    }\n\n    /// @notice Returns message's body field as an untyped memory view.\n    function body(Message message) internal pure returns (MemView) {\n        MemView memView = message.unwrap();\n        return _body(memView);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns message's padded header without checking that it is a valid header.\n    function _header(MemView memView) private pure returns (uint256) {\n        return memView.indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH});\n    }\n\n    /// @dev Returns an untyped memory view over the body field without checking\n    /// if the whole payload or the body are properly formatted.\n    function _body(MemView memView) private pure returns (MemView) {\n        return memView.sliceFrom({index_: OFFSET_BODY});\n    }\n}\n\n// contracts/base/AgentSecured.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for messaging contracts that are secured by the agent manager.\n * `AgentSecured` relies on `AgentManager` to provide the following functionality:\n * - Keep track of agents and their statuses.\n * - Pass agent-signed statements that were verified by the agent manager.\n * - These statements are considered valid indefinitely, unless the agent is disputed.\n * - Disputes are opened and resolved by the agent manager.\n * \u003e `AgentSecured` implementation should never use statements signed by agents that are disputed.\n */\nabstract contract AgentSecured is MessagingBase, IAgentSecured {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    address public immutable agentManager;\n\n    /// @inheritdoc IAgentSecured\n    address public immutable inbox;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    // (agent index =\u003e their dispute status: flag, openedAt, resolvedAt)\n    mapping(uint32 =\u003e DisputeStatus) internal _disputes;\n\n    /// @dev gap for upgrade safety\n    uint256[49] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    modifier onlyAgentManager() {\n        if (msg.sender != agentManager) revert CallerNotAgentManager();\n        _;\n    }\n\n    modifier onlyInbox() {\n        if (msg.sender != inbox) revert CallerNotInbox();\n        _;\n    }\n\n    constructor(string memory version_, uint32 synapseDomain_, address agentManager_, address inbox_)\n        MessagingBase(version_, synapseDomain_)\n    {\n        agentManager = agentManager_;\n        inbox = inbox_;\n    }\n\n    // ════════════════════════════════════════════ ONLY AGENT MANAGER ═════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external onlyAgentManager {\n        uint40 openedAt = ChainContext.blockTimestamp();\n        DisputeStatus memory status = DisputeStatus({flag: DisputeFlag.Pending, openedAt: openedAt, resolvedAt: 0});\n        _disputes[guardIndex] = status;\n        _disputes[notaryIndex] = status;\n    }\n\n    /// @inheritdoc IAgentSecured\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external onlyAgentManager {\n        // Update the dispute status of the slashed agent first.\n        uint40 resolvedAt = ChainContext.blockTimestamp();\n        _disputes[slashedIndex].flag = DisputeFlag.Slashed;\n        _disputes[slashedIndex].resolvedAt = resolvedAt;\n        // Mark the rival agent as not disputed, if there was an ongoing dispute.\n        if (rivalIndex != 0) {\n            _disputes[rivalIndex].flag = DisputeFlag.None;\n            _disputes[rivalIndex].resolvedAt = resolvedAt;\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function agentStatus(address agent) external view returns (AgentStatus memory) {\n        return _agentStatus(agent);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status) {\n        return _getAgent(index);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory) {\n        return _disputes[agentIndex];\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns status of the given agent: (flag, domain, index).\n    function _agentStatus(address agent) internal view returns (AgentStatus memory) {\n        return IAgentManager(agentManager).agentStatus(agent);\n    }\n\n    /// @dev Returns agent and their status for a given agent index. Returns zero values for non existing indexes.\n    function _getAgent(uint256 index) internal view returns (address agent, AgentStatus memory status) {\n        return IAgentManager(agentManager).getAgent(index);\n    }\n\n    /// @dev Checks if a Dispute exists for the given Notary. This function returns true, if\n    /// Notary is in ongoing Dispute, or if Dispute was resolved not in Notary's favor.\n    /// In both cases we can't trust Notary's data.\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeExists(uint32 notaryIndex) internal view returns (bool) {\n        return _disputes[notaryIndex].flag != DisputeFlag.None;\n    }\n\n    /// @dev Checks if a Notary recently won a Dispute and is still in the \"post-dispute\" timeout period.\n    /// In this period we still can't trust Notary's data, though we can optimistically assume that\n    /// that the data will be correct after the timeout (assuming no new Disputes are opened).\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeTimeout(uint32 notaryIndex) internal view returns (bool) {\n        DisputeStatus memory status = _disputes[notaryIndex];\n        // Exit early if Notary is in ongoing Dispute / slashed.\n        if (status.flag != DisputeFlag.None) return false;\n        // Check if Notary has been in any Dispute at all.\n        if (status.openedAt == 0) return false;\n        // Otherwise check if the Dispute timeout is still active.\n        return block.timestamp \u003c status.resolvedAt + DISPUTE_TIMEOUT_NOTARY;\n    }\n}\n\n// contracts/hubs/StateHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StateHub` is a parent contract for `Origin`. It is responsible for the following:\n/// - Keeping track of the historical Origin Merkle Tree containing all the message hashes.\n/// - Keeping track of the historical Origin States, as well as verifying their validity.\nabstract contract StateHub is AgentSecured, StateHubEvents, IStateHub {\n    using SafeCast for uint256;\n    using StateLib for bytes;\n\n    struct OriginState {\n        uint40 blockNumber;\n        uint40 timestamp;\n        GasData gasData;\n    }\n    // Bits left for tight packing: 80\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Historical Merkle Tree\n    /// Note: Takes two storage slots\n    HistoricalTree private _tree;\n\n    /// @dev All historical contract States\n    OriginState[] private _originStates;\n\n    /// @dev gap for upgrade safety\n    uint256[47] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IStateHub\n    function isValidState(bytes memory statePayload) external view returns (bool isValid) {\n        // This will revert if payload is not a formatted state\n        State state = statePayload.castToState();\n        return _isValidState(state);\n    }\n\n    /// @inheritdoc IStateHub\n    function statesAmount() external view returns (uint256) {\n        return _originStates.length;\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestLatestState() external view returns (bytes memory stateData) {\n        // This never underflows, assuming the contract was initialized\n        return suggestState(_nextNonce() - 1);\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestState(uint32 nonce) public view returns (bytes memory stateData) {\n        // This will revert if nonce is out of range\n        bytes32 root = _tree.root(nonce);\n        return _formatOriginState(_originStates[nonce], root, localDomain, nonce);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Initializes the saved states list by inserting a state for an empty Merkle Tree.\n    function _initializeStates() internal {\n        // This should only be called once, when the contract is initialized\n        // This will revert if _tree.roots is non-empty\n        bytes32 savedRoot = _tree.initializeRoots();\n        // Save root for empty merkle _tree with block number and timestamp of initialization\n        _saveState(savedRoot, _toOriginState());\n    }\n\n    /// @dev Inserts leaf into the Merkle Tree and saves the updated origin State.\n    function _insertAndSave(bytes32 leaf) internal {\n        bytes32 newRoot = _tree.insert(leaf);\n        _saveState(newRoot, _toOriginState());\n    }\n\n    /// @dev Saves an updated state of the Origin contract\n    function _saveState(bytes32 root, OriginState memory state) internal {\n        uint32 nonce = _nextNonce();\n        _originStates.push(state);\n        // Emit event with raw state data\n        emit StateSaved(_formatOriginState(state, root, localDomain, nonce));\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns nonce of the next sent message: the amount of saved States so far.\n    /// This always equals to \"total amount of sent messages\" plus 1.\n    function _nextNonce() internal view returns (uint32) {\n        // TODO: consider using more than 32 bits for origin nonces\n        return _originStates.length.toUint32();\n    }\n\n    /// @dev Checks if a state is valid, i.e. if it matches the historical one.\n    /// Reverts, if state refers to another Origin contract.\n    function _isValidState(State state) internal view returns (bool) {\n        // Check if state refers to this contract\n        if (state.origin() != localDomain) revert IncorrectOriginDomain();\n        // Check if nonce exists\n        uint32 nonce = state.nonce();\n        if (nonce \u003e= _originStates.length) return false;\n        // Check if state root matches the historical one\n        if (state.root() != _tree.root(nonce)) return false;\n        // Check if state metadata matches the historical one\n        return _areEqual(state, _originStates[nonce]);\n    }\n\n    // ═════════════════════════════════════════════ STRUCT FORMATTING ═════════════════════════════════════════════════\n\n    /// @dev Returns a formatted payload for a stored OriginState.\n    function _formatOriginState(OriginState memory originState, bytes32 root, uint32 origin, uint32 nonce)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return StateLib.formatState({\n            root_: root,\n            origin_: origin,\n            nonce_: nonce,\n            blockNumber_: originState.blockNumber,\n            timestamp_: originState.timestamp,\n            gasData_: originState.gasData\n        });\n    }\n\n    /// @dev Child contract should implement the logic for getting the current gas data from the gas oracle\n    /// to be saved as part of the Origin State.\n    // solhint-disable-next-line ordering\n    function _fetchGasData() internal view virtual returns (GasData);\n\n    /// @dev Returns a OriginState struct to save in the contract.\n    function _toOriginState() internal view returns (OriginState memory originState) {\n        originState.blockNumber = ChainContext.blockNumber();\n        originState.timestamp = ChainContext.blockTimestamp();\n        originState.gasData = _fetchGasData();\n    }\n\n    /// @dev Checks that a state and its Origin representation are equal.\n    function _areEqual(State state, OriginState memory originState) internal pure returns (bool) {\n        return state.blockNumber() == originState.blockNumber \u0026\u0026 state.timestamp() == originState.timestamp;\n    }\n}\n\n// contracts/Origin.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Origin` contract is used for sending messages to remote chains. It is done\n/// by inserting the message hashes into the Origin Merkle, which makes it possible to\n/// prove that message was sent using the Merkle proof against the Origin Merkle Root. This essentially\n/// compresses the list of messages into a single 32-byte value that needs to be stored on the destination chain.\n/// `Origin` is responsible for the following:\n/// - Formatting the sent message payloads, and inserting their hashes into the Origin Merkle Tree.\n/// - Keeping track of its own historical states (see parent contract `StateHub`).\n/// - Enforcing minimum tip values for sent base messages based on the provided execution requests.\n/// - Distributing the collected tips upon request from a local `AgentManager` contract.\ncontract Origin is StateHub, OriginEvents, InterfaceOrigin {\n    using MemViewLib for bytes;\n    using MessageLib for bytes;\n    using TipsLib for bytes;\n    using TypeCasts for address;\n\n    address public immutable gasOracle;\n\n    modifier onlyRemoteDestination(uint32 destination) {\n        if (destination == localDomain) revert IncorrectDestinationDomain();\n        _;\n    }\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_, address gasOracle_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {\n        gasOracle = gasOracle_;\n    }\n\n    /// @notice Initializes Origin contract:\n    /// - msg.sender is set as contract owner\n    /// - State of \"empty merkle tree\" is saved\n    function initialize() external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize \"states\": state of an \"empty merkle tree\" is saved\n        _initializeStates();\n    }\n\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable onlyRemoteDestination(destination) returns (uint32 messageNonce, bytes32 messageHash) {\n        // Check that content is not too large\n        if (content.length \u003e MAX_CONTENT_BYTES) revert ContentLengthTooBig();\n        // This will revert if msg.value is lower than value of minimum tips\n        Tips tips = _getMinimumTips(destination, paddedRequest, content.length).matchValue(msg.value);\n        Request request = RequestLib.wrapPadded(paddedRequest);\n        // Format the BaseMessage body\n        bytes memory body = BaseMessageLib.formatBaseMessage({\n            sender_: msg.sender.addressToBytes32(),\n            recipient_: recipient,\n            tips_: tips,\n            request_: request,\n            content_: content\n        });\n        // Send the message\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Base, body);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        onlyAgentManager\n        onlyRemoteDestination(destination)\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // AgentManager (checked via modifier) is responsible for constructing the calldata payload correctly.\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Manager, payload);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function withdrawTips(address recipient, uint256 amount) external onlyAgentManager {\n        if (address(this).balance \u003c amount) revert InsufficientEthBalance();\n        (bool success,) = recipient.call{value: amount}(\"\");\n        if (!success) revert EthTransferFailed();\n        emit TipWithdrawalCompleted(recipient, amount);\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue)\n    {\n        return _getMinimumTips(destination, paddedRequest, contentLength).value();\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Sends the given message to the specified destination. Message hash is inserted\n    /// into the Origin Merkle Tree, which will enable message execution on destination chain.\n    function _sendMessage(uint32 destination, uint32 optimisticPeriod, MessageFlag flag, bytes memory body)\n        internal\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // Format the message header\n        messageNonce = _nextNonce();\n        Header header = flag.encodeHeader({\n            origin_: localDomain,\n            nonce_: messageNonce,\n            destination_: destination,\n            optimisticPeriod_: optimisticPeriod\n        });\n        // Format the full message payload\n        bytes memory msgPayload = MessageLib.formatMessage(header, body);\n        // Insert new leaf into the Origin Merkle Tree and save the updated state\n        messageHash = msgPayload.castToMessage().leaf();\n        _insertAndSave(messageHash);\n        // Emit event with message information\n        emit Sent(messageHash, messageNonce, destination, msgPayload);\n        // Update the gas oracle data. We do this after the provided tips are checked so that\n        // the provided message is sent in the event that the gas oracle data is updated to a higher value.\n        InterfaceGasOracle(gasOracle).updateGasData(destination);\n        // TODO: consider doing this before the message is sent, while adjusting GasOracle.getMinimumTips() to\n        // use the pending gas oracle data.\n    }\n\n    /// @dev Returns the minimum tips for sending a message to the given destination with the given request and content.\n    function _getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        internal\n        view\n        returns (Tips)\n    {\n        return\n            TipsLib.wrapPadded(InterfaceGasOracle(gasOracle).getMinimumTips(destination, paddedRequest, contentLength));\n    }\n\n    /// @dev Gets the current gas data from the gas oracle to be saved as part of the Origin State.\n    function _fetchGasData() internal view override returns (GasData) {\n        return GasDataLib.wrapGasData(InterfaceGasOracle(gasOracle).getGasData());\n    }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"219690:6741:0:-:0;;;220418:206;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;206150:219;;;;;;;;;;;;;-1:-1:-1;;;206150:219:0;;;;75476:32;;220542:14;220558:13;220573:6;206150:219;220542:14;206150:219;75742:24;75756:8;75742:24;:::i;:::-;75734:32;;;;;;75430:343;197653:22:::1;:20;;;;;:22;;:::i;:::-;197639:36;::::0;;::::1;;::::0;197685:30:::1;;::::0;-1:-1:-1;;;;;;206310:28:0;;::::1;;::::0;206348:14;::::1;;::::0;220595:22;;;::::1;;::::0;-1:-1:-1;219690:6741:0;;-1:-1:-1;;;;219690:6741:0;77317:98;77359:6;77384:24;:13;:22;;;;;:24;;:::i;:::-;77377:31;;77317:98;:::o;43438:187::-;43494:6;43529:16;43520:25;;;43512:76;;;;-1:-1:-1;;;43512:76:0;;1241:2:1;43512:76:0;;;1223:21:1;1280:2;1260:18;;;1253:30;1319:34;1299:18;;;1292:62;-1:-1:-1;;;1370:18:1;;;1363:36;1416:19;;43512:76:0;;;;;;;;-1:-1:-1;43612:5:0;43438:187::o;14:177:1:-;93:13;;-1:-1:-1;;;;;135:31:1;;125:42;;115:70;;181:1;178;171:12;115:70;14:177;;;:::o;196:536::-;292:6;300;308;316;369:3;357:9;348:7;344:23;340:33;337:53;;;386:1;383;376:12;337:53;418:9;412:16;468:10;461:5;457:22;450:5;447:33;437:61;;494:1;491;484:12;437:61;517:5;-1:-1:-1;541:49:1;586:2;571:18;;541:49;:::i;:::-;531:59;;609:49;654:2;643:9;639:18;609:49;:::i;:::-;599:59;;677:49;722:2;711:9;707:18;677:49;:::i;:::-;667:59;;196:536;;;;;;;:::o;737:297::-;855:12;;902:4;891:16;;;885:23;;855:12;920:16;;917:111;;;1014:1;1010:6;1000;994:4;990:17;987:1;983:25;979:38;972:5;968:50;959:59;;917:111;;737:297;;;:::o;1039:402::-;219690:6741:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","srcMapRuntime":"219690:6741:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;208058:122;;;;;;;;;;-1:-1:-1;208058:122:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;208220:138;;;;;;;;;;-1:-1:-1;208220:138:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;222965:334::-;;;;;;;;;;-1:-1:-1;222965:334:0;;;;;:::i;:::-;;:::i;:::-;;223675:255;;;;;;;;;;-1:-1:-1;223675:255:0;;;;;:::i;:::-;;:::i;:::-;;;2798:25:1;;;2786:2;2771:18;223675:255:0;2652:177:1;75779:401:0;;;;;;;;;;-1:-1:-1;75950:28:0;;;;;;;;;75963:7;75950:28;;75972:5;75950:28;;;;75779:401;;;;;;;:::i;219882:34::-;;;;;;;;;;;;;;;;;;3825:42:1;3813:55;;;3795:74;;3783:2;3768:18;219882:34:0;3649:226:1;73126:1352:0;;;;;;;;;;-1:-1:-1;73126:1352:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;207105:579::-;;;;;;;;;;-1:-1:-1;207105:579:0;;;;;:::i;:::-;;:::i;197947:57::-;;;;;;;;;;;;;:::i;197065:37::-;;;;;;;;;;;;;;;;;;6192:10:1;6180:23;;;6162:42;;6150:2;6135:18;197065:37:0;6018:192:1;205236:37:0;;;;;;;;;;;;;;;179664:212;;;;;;;;;;;;;:::i;220769:243::-;;;;;;;;;;;;;:::i;221372:1058::-;;;;;;:::i;:::-;;:::i;:::-;;;;8123:10:1;8111:23;;;8093:42;;8166:2;8151:18;;8144:34;;;;8066:18;221372:1058:0;7921:263:1;196948:35:0;;;;;;;;;;;;;;;175995:85;;;;;;;;;;-1:-1:-1;176067:6:0;;;;175995:85;;222472:451;;;;;;;;;;-1:-1:-1;222472:451:0;;;;;:::i;:::-;;:::i;206717:348::-;;;;;;;;;;-1:-1:-1;206717:348:0;;;;;:::i;:::-;;:::i;213082:244::-;;;;;;;;;;-1:-1:-1;213082:244:0;;;;;:::i;:::-;;:::i;:::-;;;9276:14:1;;9269:22;9251:41;;9239:2;9224:18;213082:244:0;9111:187:1;213737:266:0;;;;;;;;;;-1:-1:-1;213737:266:0;;;;;:::i;:::-;;:::i;213498:203::-;;;;;;;;;;;;;:::i;208398:138::-;;;;;;;;;;-1:-1:-1;208398:138:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;178777:99::-;;;;;;;;;;-1:-1:-1;178856:13:0;;;;178777:99;;213362:100;;;;;;;;;;-1:-1:-1;213435:13:0;:20;213362:100;;179069:178;;;;;;;;;;-1:-1:-1;179069:178:0;;;;;:::i;:::-;;:::i;205314:30::-;;;;;;;;;;;;;;;208058:122;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;208154:19:0;208167:5;208154:12;:19::i;:::-;208147:26;208058:122;-1:-1:-1;;208058:122:0:o;208220:138::-;-1:-1:-1;;;;;;;;208276:13:0;-1:-1:-1;;;;;;;;;;;;;;;208335:16:0;208345:5;208335:9;:16::i;:::-;208328:23;;;;208220:138;;;:::o;222965:334::-;205965:10;:26;205979:12;205965:26;;205961:62;;206000:23;;;;;;;;;;;;;;205961:62;223086:6:::1;223062:21;:30;223058:67;;;223101:24;;;;;;;;;;;;;;223058:67;223136:12;223153:9;:14;;223175:6;223153:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;223135:51;;;223201:7;223196:40;;223217:19;;;;;;;;;;;;;;223196:40;223251:41;::::0;;10730:42:1;10718:55;;10700:74;;10805:2;10790:18;;10783:34;;;223251:41:0::1;::::0;10673:18:1;223251:41:0::1;;;;;;;;223048:251;222965:334:::0;;:::o;223675:255::-;223817:17;223857:66;:58;223873:11;223886:13;223901;223857:15;:58::i;:::-;:64;:66::i;:::-;223850:73;;223675:255;;;;;;:::o;73126:1352::-;73186:27;73242:5;;73278:20;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;73278:20:0;;;;;;;;;;;;;;;;73264:34;;73308:19;73342:9;73337:1135;73361:6;73357:1;:10;73337:1135;;;73392:5;;73398:1;73392:8;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;73384:16;;73414:20;73437:11;73449:1;73437:14;;;;;;;;:::i;:::-;;;;;;;73414:37;;73794:4;73786:26;;73813:5;:14;;;;;;;;:::i;:::-;73786:42;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;73765:17:0;;;73748:80;;;;;;74101:19;;74098:38;74088:301;;74265:66;74259:4;74252:80;74366:4;74360;74353:18;74088:301;-1:-1:-1;74444:3:0;;73337:1135;;;;73215:1263;;73126:1352;;;;:::o;207105:579::-;205965:10;:26;205979:12;205965:26;;205961:62;;206000:23;;;;;;;;;;;;;;205961:62;207270:17:::1;207290:29;:27;:29::i;:::-;207329:23;::::0;;::::1;;::::0;;;:9:::1;:23;::::0;;;;:50;;207389:47:::1;::::0;::::1;::::0;::::1;::::0;;;;;207360:19:::1;207389:47:::0;;;207270:49;;-1:-1:-1;207532:15:0;::::1;::::0;207528:150:::1;;207563:21;::::0;::::1;207592:16;207563:21:::0;;;:9:::1;:21;::::0;;;;:45;;207622;;;::::1;::::0;::::1;;;::::0;;207528:150:::1;207195:489;207105:579:::0;;:::o;197947:57::-;175888:13;:11;:13::i;:::-;197947:57::o;179664:212::-;178856:13;;153704:10;;179763:24;178856:13;179763:24;;179755:78;;;;;;;12465:2:1;179755:78:0;;;12447:21:1;12504:2;12484:18;;;12477:30;12543:34;12523:18;;;12516:62;12614:11;12594:18;;;12587:39;12643:19;;179755:78:0;;;;;;;;;179843:26;179862:6;179843:18;:26::i;:::-;179706:170;179664:212::o;220769:243::-;131870:19;131893:13;;;;;;131892:14;;131938:34;;;;-1:-1:-1;131956:12:0;;131971:1;131956:12;;;;:16;131938:34;131937:108;;;-1:-1:-1;132017:4:0;64994:19;:23;;;131978:66;;-1:-1:-1;132027:12:0;;;;;:17;131978:66;131916:201;;;;;;;12875:2:1;131916:201:0;;;12857:21:1;12914:2;12894:18;;;12887:30;12953:34;12933:18;;;12926:62;13024:16;13004:18;;;12997:44;13058:19;;131916:201:0;12673:410:1;131916:201:0;132127:12;:16;;;;132142:1;132127:16;;;132153:65;;;;132187:13;:20;;;;;;;;132153:65;220882:21:::1;:19;:21::i;:::-;220986:19;:17;:19::i;:::-;132242:14:::0;132238:99;;;132288:5;132272:21;;;;;;132312:14;;-1:-1:-1;13240:36:1;;132312:14:0;;13228:2:1;13213:18;132312:14:0;;;;;;;131860:483;220769:243::o;221372:1058::-;221613:19;221634;221591:11;220003;219988:26;;:11;:26;;;219984:67;;220023:28;;;;;;;;;;;;;;219984:67;13524:11:::1;221716:7;:14;:34;221712:68;;;221759:21;;;;;;;;;;;;;;221712:68;221867:9;221879:81;221950:9;221879:59;221895:11;221908:13;221923:7;:14;221879:15;:59::i;:::-;:70:::0;::::1;:81::i;:::-;221867:93:::0;-1:-1:-1;222010:13:0;221970:15:::1;222093:218;221867:93:::0;222149:10:::1;222204:9:::0;222010:13;222293:7;222093:32:::1;:218::i;:::-;222073:238;;222356:67;222369:11;222382:16;222400;222418:4;222356:12;:67::i;:::-;222349:74;;;;;;;221372:1058:::0;;;;;;;;;:::o;222472:451::-;222669:19;;205965:10;:26;205979:12;205965:26;;205961:62;;206000:23;;;;;;;;;;;;;;205961:62;222639:11:::1;220003;219988:26;;:11;:26;;::::0;219984:67:::1;;220023:28;;;;;;;;;;;;;;219984:67;222843:73:::2;222856:11;222869:16;222887:19;222908:7;222843:12;:73::i;:::-;222836:80;;;;206033:1:::1;222472:451:::0;;;;;;:::o;206717:348::-;205965:10;:26;205979:12;205965:26;;205961:62;;206000:23;;;;;;;;;;;;;;205961:62;206813:15:::1;206831:29;:27;:29::i;:::-;206813:47;;206870:27;206900:77;;;;;;;;206921:19;206900:77;;;;;;;;:::i;:::-;::::0;;::::1;::::0;::::1;;::::0;;::::1;::::0;;;;-1:-1:-1;206900:77:0;;;;;;;206987:21:::1;::::0;::::1;::::0;;:9:::1;:21:::0;;;;:30;;;;206870:107;;-1:-1:-1;206870:107:0;;206987:21;;:30;::::1;::::0;;::::1;::::0;::::1;;;;;;:::i;:::-;;;::::0;;-1:-1:-1;206987:30:0::1;::::0;;::::1;::::0;;;::::1;::::0;;::::1;::::0;::::1;::::0;;::::1;::::0;::::1;::::0;;;;::::1;;;::::0;;;;;;::::1;::::0;;;207027:22:::1;::::0;::::1;206987:30;207027:22:::0;;;:9:::1;:22:::0;;;;:31;;;;207052:6;;207027:22;:31;:22;;:31;::::1;206987:30;207027:31:::0;::::1;::::0;::::1;;;;;;:::i;:::-;;;::::0;;-1:-1:-1;207027:31:0::1;::::0;::::1;::::0;;;::::1;::::0;;::::1;::::0;;;;;::::1;;::::0;;::::1;;::::0;;;;;;;::::1;;::::0;;;::::1;::::0;;-1:-1:-1;;;;206717:348:0:o;213082:244::-;213154:12;213242:11;213256:26;:12;:24;:26::i;:::-;213242:40;;213299:20;213313:5;213299:13;:20::i;213737:266::-;213794:22;213881:12;213896:17;:5;:17;;;;;:10;:17;:::i;:::-;213881:32;;213930:66;213949:13;213963:5;213949:20;;;;;;;;;;:::i;:::-;;;;;;;;;;213930:66;;;;;;;;213949:20;;;;213930:66;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;213971:4;213977:11;213990:5;213930:18;:66::i;213498:203::-;213551:22;213664:30;213692:1;213677:12;:10;:12::i;:::-;:16;;;;:::i;213664:30::-;213657:37;;213498:203;:::o;208398:138::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;208508:21:0;;;;;;;:9;:21;;;;;;;208501:28;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;208398:138;-1:-1:-1;;208398:138:0:o;179069:178::-;175888:13;:11;:13::i;:::-;179158::::1;:24:::0;;::::1;::::0;::::1;::::0;;;::::1;::::0;::::1;::::0;;;179222:7:::1;176067:6:::0;;;;;175995:85;179222:7:::1;179197:43;;;;;;;;;;;;179069:178:::0;:::o;77317:98::-;77359:6;77384:24;:13;43438:187;43494:6;43529:16;43520:25;;;43512:76;;;;;;;13858:2:1;43512:76:0;;;13840:21:1;13897:2;13877:18;;;13870:30;13936:34;13916:18;;;13909:62;14007:8;13987:18;;;13980:36;14033:19;;43512:76:0;13656:402:1;43512:76:0;-1:-1:-1;43612:5:0;43438:187::o;208929:150::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;209026:46:0;;;;;:39;3813:55:1;;;209026:46:0;;;3795:74:1;209040:12:0;209026:39;;;;3768:18:1;;209026:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;209200:166::-;-1:-1:-1;;;;;;;;209257:13:0;-1:-1:-1;;;;;;;;;;;;;;;209316:43:0;;;;;;;;2798:25:1;;;209330:12:0;209316:36;;;;;2771:18:1;;209316:43:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;225876:291::-;226072:87;;;;;;15697:23:1;;226072:87:0;;;15679:42:1;15737:18;;;15730:34;;;15780:18;;;15773:34;;;226014:4:0;;226053:107;;226072:44;226091:9;226072:44;;;;15652:18:1;;226072:87:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;27198:13;26993:227;173393:220;173442:14;173551:4;173477:92;;173529:19;:4;168264:5;172631:40;;172452:227;173529:19;173477:71;;173505:21;:4;168146:6;172353:42;;172172:231;173505:21;173477:49;;173485:16;:4;168024:6;172076:37;;171900:221;173485:16;173477:25;;:49;;;;:::i;:::-;:71;;;;:::i;:::-;:92;;;;:::i;:::-;11744:2;173579:27;;173393:220;-1:-1:-1;;173393:220:0:o;77043:107::-;77092:6;77117:26;:15;:24;:26::i;176153:130::-;176067:6;;176216:23;176067:6;153704:10;176216:23;176208:68;;;;;;;16339:2:1;176208:68:0;;;16321:21:1;;;16358:18;;;16351:30;16417:34;16397:18;;;16390:62;16469:18;;176208:68:0;16137:356:1;179431:153:0;179520:13;179513:20;;;;;;179543:34;179568:8;179543:24;:34::i;178392:100::-;133965:13;;;;;;;133957:69;;;;;;;16700:2:1;133957:69:0;;;16682:21:1;16739:2;16719:18;;;16712:30;16778:34;16758:18;;;16751:62;16849:13;16829:18;;;16822:41;16880:19;;133957:69:0;16498:407:1;133957:69:0;178459:26:::1;:24;:26::i;214419:374::-:0;214600:17;214620:23;:5;:21;:23::i;:::-;214600:43;;214747:39;214758:9;214769:16;:14;:16::i;:::-;214747:10;:39::i;173686:924::-;173758:12;173782:16;173801:12;:4;:10;:12::i;:::-;173782:31;;173838:8;173827;:19;173823:49;;;173855:17;;;;;;;;;;;;;;173823:49;174010:19;;;11744:2;174009:41;174304:16;174283:4;174275:26;;:5;:26;:45;174271:72;;;174329:14;;;;;;;;;;;;;;174271:72;174567:25;;;;;173686:924;-1:-1:-1;;;173686:924:0:o;191960:270::-;192124:12;192176:5;192183:7;192192:10;192204:8;192214;192159:64;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;192152:71;;191960:270;;;;;;;:::o;224439:1310::-;224577:19;224598;224685:12;:10;:12::i;:::-;224670:27;;224707:13;224723:185;224764:11;224797:12;224837:11;224881:16;224723:4;:17;;;;;;;;:::i;:::-;;:185;;;:17;:185::i;:::-;224707:201;;224961:23;224987:38;225012:6;225020:4;224987:24;:38::i;:::-;224961:64;;225131:33;:26;:10;:24;:26::i;:::-;:31;:33::i;:::-;225117:47;;225174:27;225189:11;225174:14;:27::i;:::-;225295:11;225263:56;;225281:12;225263:56;;225268:11;225263:56;225308:10;225263:56;;;;;;:::i;:::-;;;;;;;;225531;;;;;6192:10:1;6180:23;;225531:56:0;;;6162:42:1;225550:9:0;225531:43;;;;;6135:18:1;;225531:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;224623:1126;;224439:1310;;;;;;;:::o;183679:123::-;183745:5;183769:26;183781:13;:7;:11;:13::i;:::-;183769:11;:26::i;216165:561::-;216224:4;216312:11;216294:29;;:14;:5;:12;:14::i;:::-;:29;;;216290:65;;216332:23;;;;;;;;;;;;;;216290:65;216398:12;216413:13;:5;:11;:13::i;:::-;216449;:20;216398:28;;-1:-1:-1;216440:29:0;;;;216436:47;;-1:-1:-1;216478:5:0;;216165:561;-1:-1:-1;;216165:561:0:o;216436:47::-;216571:17;:5;:17;;;;;:10;:17;:::i;:::-;216555:12;:5;:10;:12::i;:::-;:33;216551:51;;-1:-1:-1;216597:5:0;;216165:561;-1:-1:-1;;216165:561:0:o;216551:51::-;216681:38;216691:5;216698:13;216712:5;216698:20;;;;;;;;;;:::i;:::-;;;;;;;;;;216681:38;;;;;;;;216698:20;;;;216681:38;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:9;:38::i;163570:211::-;163698:10;;;:17;163651:22;;163689:26;;163685:55;;163724:16;;;;;;;;;;;;;;163685:55;163757:4;:10;;163768:5;163757:17;;;;;;;;:::i;:::-;;;;;;;;;163750:24;;163570:211;;;;:::o;217109:446::-;217259:12;217294:254;217336:4;217363:6;217391:5;217424:11;:23;;;217473:11;:21;;;217518:11;:19;;;183459:76;;;;;;18965:19:1;;;;19107:3;19103:16;;;19003:66;19099:25;;;19085:12;;;19078:47;19159:16;;;;19155:25;;;19141:12;;;19134:47;19304:3;19300:16;;;19200:66;19296:25;;;19282:12;;;19275:47;19356:16;;19352:25;19338:12;;;19331:47;19416:3;19412:16;19430:66;19408:89;19394:12;;;19387:111;183459:76:0;;;;;;;;;19514:12:1;;;;183459:76:0;;;183226:316;217294:254;217287:261;217109:446;-1:-1:-1;;;;;217109:446:0:o;215842:176::-;215980:13;:20;215887:6;;215980:31;;:29;:31::i;42926:187::-;42982:6;43017:16;43008:25;;;43000:76;;;;;;;17807:2:1;43000:76:0;;;17789:21:1;17846:2;17826:18;;;17819:30;17885:34;17865:18;;;17858:62;17956:8;17936:18;;;17929:36;17982:19;;43000:76:0;17605:402:1;177220:187:0;177312:6;;;;177328:17;;;;;;;;;;;177360:40;;177312:6;;;177328:17;177312:6;;177360:40;;177293:16;;177360:40;177283:124;177220:187;:::o;175658:111::-;133965:13;;;;;;;133957:69;;;;;;;16700:2:1;133957:69:0;;;16682:21:1;16739:2;16719:18;;;16712:30;16778:34;16758:18;;;16751:62;16849:13;16829:18;;;16822:41;16880:19;;133957:69:0;16498:407:1;133957:69:0;175730:32:::1;153704:10:::0;175730:18:::1;:32::i;162344:306::-:0;162529:10;;;:17;162416;;162529:22;162522:30;;;;:::i;:::-;162617:10;;;;:26;;;;;;;-1:-1:-1;162617:26:0;;;;;;;;;;;;162633:9;162344:306::o;217898:260::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;218015:26:0;:24;:26::i;:::-;217989:52;;;;218075:29;:27;:29::i;:::-;218051:53;;:21;;;:53;218136:15;:13;:15::i;:::-;218114:37;;:19;;;:37;:11;217898:260::o;215094:268::-;215173:12;215188;:10;:12::i;:::-;215210:13;:25;;;;;;;-1:-1:-1;215210:25:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;215173:27;-1:-1:-1;215292:63:0;215303:51;215229:5;215329:4;215335:11;215173:27;215303:18;:51::i;:::-;215292:63;;;;;;:::i;124239:576::-;124427:6;124772:26;;;124715:42;123899:5;124715:42;;;;124670:30;123785:5;124670:30;;;;124623:32;123682:6;124623:32;;;;123577:6;124587:5;124581:12;;;;;;;;:::i;:::-;124573:21;;:35;;:82;:127;:184;:225;;124239:576;-1:-1:-1;;;;;;124239:576:0:o;199727:152::-;199809:12;199857:7;199866:5;199840:32;;;;;;;;;:::i;:::-;;;;;;;;;;;;;199833:39;;199727:152;;;;:::o;200032:129::-;200100:7;200126:28;200140:13;:7;:11;:13::i;:::-;200126;:28::i;201672:522::-;201726:7;201831:14;201848:16;:7;:14;:16::i;:::-;201831:33;-1:-1:-1;201945:16:0;201927:14;:7;:12;;;:14::i;:::-;:34;;;;;;;;:::i;:::-;;201923:265;;201984:79;202005:14;:7;:12;;126008:20;126164:17;;;126280:2;126267:16;;;125956:343;202005:14;202021:41;:34;:14;:7;:12;:14::i;:::-;:32;:34::i;:::-;:39;:41::i;:::-;201984:20;:79::i;201923:265::-;202101:76;202122:14;:7;:12;;126008:20;126164:17;;;126280:2;126267:16;;;125956:343;202122:14;202138:38;:31;:14;:7;:12;:14::i;:::-;:29;:31::i;:::-;:36;:38::i;214882:147::-;214939:15;214957:18;:5;214970:4;214957:12;:18::i;:::-;214939:36;;214985:37;214996:7;215005:16;:14;:16::i;214985:37::-;214929:100;214882:147;:::o;85007:569::-;85095:10;;85061:7;;85521:4;85512:14;;85552:17;85512:14;85095:10;85552:5;:17::i;:::-;85545:24;85007:569;-1:-1:-1;;;;85007:569:0:o;183940:185::-;184001:5;184023:16;184031:7;184023;:16::i;:::-;184018:48;;184048:18;;;;;;;;;;;;;;187847:218;187899:6;187997:60;182214:2;188054:1;187997:5;:14;:24;:60;:24;:60::i;188166:216::-;188217:6;188315:59;182262:2;188371:1;188315:5;:14;26993:227;187624:138;187674:7;187700:55;:5;187674:7;187751:2;187700:20;:55::i;218238:209::-;218371:23;;218325:4;;218348:46;;:19;:5;:17;:19::i;:::-;:46;;;:92;;;;;218419:11;:21;;;218398:42;;:17;:5;:15;:17::i;:::-;:42;;;218341:99;218238:209;-1:-1:-1;;;218238:209:0:o;76743:101::-;76789:6;76814:23;:12;:21;:23::i;226273:156::-;226330:7;226356:66;226398:9;226379:40;;;:42;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;200311:195;200374:7;200398:18;200408:7;200398:9;:18::i;:::-;200393:52;;200425:20;;;;;;;;;;;;;;202570:186;202626:6;202651:98;202673:74;202626:6;11444:2;202673:7;:16;26993:227;202673:74;202651:20;:98::i;126665:223::-;126717:11;126852:28;126872:6;126852:28;;123577:6;128573:26;;128394:213;126852:28;126840:41;;;;;;;;;;:::i;202834:145::-;202888:7;202925;202958:14;202925:7;202958:5;:14::i;192680:215::-;192747:11;192775:22;192789:7;192775:13;:22::i;:::-;192770:60;;192806:24;;;;;;;;;;;;;;193523:255;193585:7;193700:71;193721:25;:18;:11;:16;:18::i;:::-;126008:20;126164:17;;;126280:2;126267:16;;;125956:343;193721:25;193748:22;:11;:20;:22::i;105482:287::-;105563:14;105593:23;;:51;;;;-1:-1:-1;105620:24:0;;105593:51;105589:174;;;-1:-1:-1;105667:1:0;105660:8;;105589:174;105716:35;;;;;;19694:19:1;;;19729:12;;;19722:28;;;19766:12;;105716:35:0;;;;;;;;;;;;105706:46;;;;;;105699:53;;;;149497:200;149561:8;149586:19;149597:7;149586:10;:19::i;:::-;149581:54;;149614:21;;;;;;;;;;;;;;150519:115;150575:7;150601:26;:8;:24;:26::i;:17::-;:24;:26::i;162875:404::-;163098:10;;;:17;162952:15;;163125:36;163098:4;:17;163156:4;163125:20;:36::i;:::-;163210:28;:4;163229:8;163210:18;:28::i;:::-;163248:10;;;;:24;;;;;;;-1:-1:-1;163248:24:0;;;;;;;;;;;;-1:-1:-1;163200:38:0;;162875:404;-1:-1:-1;;162875:404:0:o;84127:540::-;84193:7;;84227:11;84234:4;84227;:11;:::i;:::-;84212:26;;84506:4;84500:11;84494:4;84491:21;84488:38;;;-1:-1:-1;84523:1:0;84488:38;84549:4;84557:1;84549:9;84545:66;;84581:19;;;;;;;;;;;;;;84545:66;99397:3;99389:11;;;99388:20;;84627:33;99064:352;184191:116;184248:4;10930:20;10650:2;10930;:20;:::i;:::-;89300:17;89274:43;;184271:29;;184191:116;-1:-1:-1;;184191:116:0:o;97587:538::-;97678:7;;97720:29;:7;97734:6;97742;97720:13;:29::i;:::-;98090:2;:11;;;98106:1;98089:18;98063:45;;-1:-1:-1;;97587:538:0;;;;;:::o;95895:1334::-;95982:14;96012:6;96022:1;96012:11;96008:59;;-1:-1:-1;96054:1:0;96039:17;;96008:59;96153:2;96144:6;:11;96140:65;;;96178:16;;;;;;;;;;;;;;96140:65;89300:17;89274:43;;96284:15;96293:6;96284;:15;:::i;:::-;:31;96280:82;;;96338:13;;;;;;;;;;;;;;96280:82;96401:1;96391:11;;;96371:17;96441:13;:7;168146:6;172353:42;;172172:231;96441:13;97188:17;;;97182:24;96899:66;96880:17;;;;;96876:90;;;;97178:35;;95895:1334;-1:-1:-1;;;;95895:1334:0:o;188460:229::-;188517:6;188615:66;182317:2;188678:1;188615:5;:14;26993:227;188836:224;188891:6;188989:63;182369:2;189049:1;188989:5;:14;26993:227;200589:803;200648:4;89300:17;89274:43;;199093:29;11444:2;200648:4;199093:29;:::i;:::-;200757:6;:20;200753:38;;;-1:-1:-1;200786:5:0;;200589:803;-1:-1:-1;;200589:803:0:o;200753:38::-;200839:20;200862:16;200870:7;200862;:16::i;:::-;200839:39;-1:-1:-1;125045:21:0;125016:51;123577:6;128573:26;;;125016:51;;;200888;;-1:-1:-1;200934:5:0;;200589:803;-1:-1:-1;;;200589:803:0:o;200888:51::-;201109:16;201064:41;:34;201085:12;201064:20;:34::i;:::-;:39;;;:41::i;:::-;:61;;;;;;;;:::i;:::-;;201060:326;;201205:30;:14;201211:7;201205:5;:14::i;:::-;:28;:30::i;201060:326::-;201348:27;:14;201354:7;201348:5;:14::i;:::-;:25;:27::i;125526:328::-;125591:6;125045:21;125016:51;123577:6;128573:26;;;125016:51;;;125652:52;;125688:16;;;;;;;;;;;;;;203694:127;203748:7;203774:40;199093:29;11444:2;203748:7;199093:29;:::i;:::-;203774:7;;:17;:40::i;192967:241::-;193030:4;11539:2;191061:30;11636:2;191011;191061:30;:::i;:::-;191139:31;;;;:::i;:::-;89300:17;89274:43;;193111:31;;;192967:241;-1:-1:-1;;192967:241:0:o;194401:188::-;194463:4;194486:96;194506:74;194463:4;11636:2;194506:11;:20;26993:227;193869:163;193935:7;193961:64;:55;:11;190959:2;193961:30;:55::i;149857:362::-;149917:4;89300:17;89274:43;;144397:1;150038:24;;150034:42;;;-1:-1:-1;150071:5:0;;149857:362;-1:-1:-1;;149857:362:0:o;150034:42::-;150176:36;150187:24;144397:1;150187:6;:24;:::i;:::-;152775:2;152766:11;:16;;152638:151;91038:292;91094:14;91120:12;91135:13;:7;168146:6;172353:42;;172172:231;91135:13;89300:17;89274:43;;;;91293:21;;;;;-1:-1:-1;;91038:292:0:o;158842:1865::-;158256:1;158230:23;10055:2;158230:1;:23;:::i;:::-;:27;;;;:::i;:::-;158940:8;:21;158936:50;;;158970:16;;;;;;;;;;;;;;158936:50;159529:9;159524:993;10055:2;159544:1;:22;159524:993;;;159588:8;159599:1;159588:12;159605:1;159587:19;159583:378;;159918:4;159901;159913:1;159901:14;;;;;;;:::i;:::-;;:21;-1:-1:-1;;;;158842:1865:0:o;159583:378::-;160310:42;160331:4;160343:1;160331:14;;;;;;;:::i;:::-;;;160347:4;160310:20;:42::i;:::-;160446:1;160433:14;;;;160303:49;;-1:-1:-1;160489:3:0;159524:993;;;-1:-1:-1;160687:13:0;;:::i;160920:972::-;160999:15;;161117:769;10055:2;161137:1;:22;161117:769;;;161261:5;161269:1;161261:9;161275:1;161260:16;161256:469;;161481:45;161502:4;161514:1;161502:14;;;;;;;:::i;161481:45::-;161471:55;;161256:469;;;161669:41;161690:7;161707:1;161669:20;:41::i;:::-;161659:51;;161256:469;161815:1;161805:11;;;;161858:3;161117:769;;;;160920:972;;;;:::o;203388:154::-;203444:7;203470:65;:7;203444;11444:2;203470:17;:65::i;93161:529::-;93236:7;89300:17;89274:43;;93343:13;;;93339:64;;;93379:13;;;;;;;;;;;;;;93339:64;93615:58;93644:6;93628:13;:7;168146:6;172353:42;;172172:231;93628:13;:22;93665:6;93658:4;:13;93615:5;:58::i;14:154:1:-;100:42;93:5;89:54;82:5;79:65;69:93;;158:1;155;148:12;173:247;232:6;285:2;273:9;264:7;260:23;256:32;253:52;;;301:1;298;291:12;253:52;340:9;327:23;359:31;384:5;359:31;:::i;425:184::-;477:77;474:1;467:88;574:4;571:1;564:15;598:4;595:1;588:15;614:369;695:5;689:12;727:1;723:2;720:9;710:43;;733:18;;:::i;:::-;762:15;;823:4;812:16;;;806:23;848:10;890:21;;;874:14;;;867:45;;;;965:4;954:16;;;948:23;944:32;928:14;;921:56;614:369::o;988:258::-;1180:2;1165:18;;1192:48;1169:9;1222:6;1192:48;:::i;1251:180::-;1310:6;1363:2;1351:9;1342:7;1338:23;1334:32;1331:52;;;1379:1;1376;1369:12;1331:52;-1:-1:-1;1402:23:1;;1251:180;-1:-1:-1;1251:180:1:o;1436:379::-;1699:42;1687:55;;1669:74;;1656:3;1641:19;;1752:57;1805:2;1790:18;;1782:6;1752:57;:::i;1820:315::-;1888:6;1896;1949:2;1937:9;1928:7;1924:23;1920:32;1917:52;;;1965:1;1962;1955:12;1917:52;2004:9;1991:23;2023:31;2048:5;2023:31;:::i;:::-;2073:5;2125:2;2110:18;;;;2097:32;;-1:-1:-1;;;1820:315:1:o;2140:121::-;2225:10;2218:5;2214:22;2207:5;2204:33;2194:61;;2251:1;2248;2241:12;2266:381;2342:6;2350;2358;2411:2;2399:9;2390:7;2386:23;2382:32;2379:52;;;2427:1;2424;2417:12;2379:52;2466:9;2453:23;2485:30;2509:5;2485:30;:::i;:::-;2534:5;2586:2;2571:18;;2558:32;;-1:-1:-1;2637:2:1;2622:18;;;2609:32;;2266:381;-1:-1:-1;;;2266:381:1:o;2834:250::-;2919:1;2929:113;2943:6;2940:1;2937:13;2929:113;;;3019:11;;;3013:18;3000:11;;;2993:39;2965:2;2958:10;2929:113;;;-1:-1:-1;;3076:1:1;3058:16;;3051:27;2834:250::o;3089:330::-;3131:3;3169:5;3163:12;3196:6;3191:3;3184:19;3212:76;3281:6;3274:4;3269:3;3265:14;3258:4;3251:5;3247:16;3212:76;:::i;:::-;3333:2;3321:15;3338:66;3317:88;3308:98;;;;3408:4;3304:109;;3089:330;-1:-1:-1;;3089:330:1:o;3424:220::-;3573:2;3562:9;3555:21;3536:4;3593:45;3634:2;3623:9;3619:18;3611:6;3593:45;:::i;3880:639::-;3990:6;3998;4051:2;4039:9;4030:7;4026:23;4022:32;4019:52;;;4067:1;4064;4057:12;4019:52;4107:9;4094:23;4136:18;4177:2;4169:6;4166:14;4163:34;;;4193:1;4190;4183:12;4163:34;4231:6;4220:9;4216:22;4206:32;;4276:7;4269:4;4265:2;4261:13;4257:27;4247:55;;4298:1;4295;4288:12;4247:55;4338:2;4325:16;4364:2;4356:6;4353:14;4350:34;;;4380:1;4377;4370:12;4350:34;4433:7;4428:2;4418:6;4415:1;4411:14;4407:2;4403:23;4399:32;4396:45;4393:65;;;4454:1;4451;4444:12;4393:65;4485:2;4477:11;;;;;4507:6;;-1:-1:-1;3880:639:1;;-1:-1:-1;;;;3880:639:1:o;4524:1100::-;4714:4;4743:2;4783;4772:9;4768:18;4813:2;4802:9;4795:21;4836:6;4871;4865:13;4902:6;4894;4887:22;4928:2;4918:12;;4961:2;4950:9;4946:18;4939:25;;5023:2;5013:6;5010:1;5006:14;4995:9;4991:30;4987:39;5061:2;5053:6;5049:15;5082:1;5092:503;5106:6;5103:1;5100:13;5092:503;;;5171:22;;;5195:66;5167:95;5155:108;;5286:13;;5341:9;;5334:17;5327:25;5312:41;;5392:11;;5386:18;5424:15;;;5417:27;;;5467:48;5499:15;;;5386:18;5467:48;:::i;:::-;5573:12;;;;5457:58;-1:-1:-1;;5538:15:1;;;;5128:1;5121:9;5092:503;;;-1:-1:-1;5612:6:1;;4524:1100;-1:-1:-1;;;;;;;;4524:1100:1:o;5629:384::-;5695:6;5703;5756:2;5744:9;5735:7;5731:23;5727:32;5724:52;;;5772:1;5769;5762:12;5724:52;5811:9;5798:23;5830:30;5854:5;5830:30;:::i;:::-;5879:5;-1:-1:-1;5936:2:1;5921:18;;5908:32;5949;5908;5949;:::i;:::-;6000:7;5990:17;;;5629:384;;;;;:::o;6215:184::-;6267:77;6264:1;6257:88;6364:4;6361:1;6354:15;6388:4;6385:1;6378:15;6404:777;6446:5;6499:3;6492:4;6484:6;6480:17;6476:27;6466:55;;6517:1;6514;6507:12;6466:55;6553:6;6540:20;6579:18;6616:2;6612;6609:10;6606:36;;;6622:18;;:::i;:::-;6756:2;6750:9;6818:4;6810:13;;6661:66;6806:22;;;6830:2;6802:31;6798:40;6786:53;;;6854:18;;;6874:22;;;6851:46;6848:72;;;6900:18;;:::i;:::-;6940:10;6936:2;6929:22;6975:2;6967:6;6960:18;7021:3;7014:4;7009:2;7001:6;6997:15;6993:26;6990:35;6987:55;;;7038:1;7035;7028:12;6987:55;7102:2;7095:4;7087:6;7083:17;7076:4;7068:6;7064:17;7051:54;7149:1;7142:4;7137:2;7129:6;7125:15;7121:26;7114:37;7169:6;7160:15;;;;;;6404:777;;;;:::o;7186:730::-;7288:6;7296;7304;7312;7320;7373:3;7361:9;7352:7;7348:23;7344:33;7341:53;;;7390:1;7387;7380:12;7341:53;7429:9;7416:23;7448:30;7472:5;7448:30;:::i;:::-;7497:5;-1:-1:-1;7549:2:1;7534:18;;7521:32;;-1:-1:-1;7605:2:1;7590:18;;7577:32;7618;7577;7618;:::i;:::-;7669:7;-1:-1:-1;7723:2:1;7708:18;;7695:32;;-1:-1:-1;7778:3:1;7763:19;;7750:33;7806:18;7795:30;;7792:50;;;7838:1;7835;7828:12;7792:50;7861:49;7902:7;7893:6;7882:9;7878:22;7861:49;:::i;:::-;7851:59;;;7186:730;;;;;;;;:::o;8189:592::-;8273:6;8281;8289;8342:2;8330:9;8321:7;8317:23;8313:32;8310:52;;;8358:1;8355;8348:12;8310:52;8397:9;8384:23;8416:30;8440:5;8416:30;:::i;:::-;8465:5;-1:-1:-1;8522:2:1;8507:18;;8494:32;8535;8494;8535;:::i;:::-;8586:7;-1:-1:-1;8644:2:1;8629:18;;8616:32;8671:18;8660:30;;8657:50;;;8703:1;8700;8693:12;8657:50;8726:49;8767:7;8758:6;8747:9;8743:22;8726:49;:::i;:::-;8716:59;;;8189:592;;;;;:::o;8786:320::-;8854:6;8907:2;8895:9;8886:7;8882:23;8878:32;8875:52;;;8923:1;8920;8913:12;8875:52;8963:9;8950:23;8996:18;8988:6;8985:30;8982:50;;;9028:1;9025;9018:12;8982:50;9051:49;9092:7;9083:6;9072:9;9068:22;9051:49;:::i;9303:245::-;9361:6;9414:2;9402:9;9393:7;9389:23;9385:32;9382:52;;;9430:1;9427;9420:12;9382:52;9469:9;9456:23;9488:30;9512:5;9488:30;:::i;9776:535::-;9994:13;;9972:2;9957:18;;;10033:1;10026:9;;10016:43;;10039:18;;:::i;:::-;10086:2;10075:9;10068:21;;10136:4;10128:6;10124:17;10118:24;10161:12;10229:2;10215:12;10211:21;10204:4;10193:9;10189:20;10182:51;10301:2;10293:4;10285:6;10281:17;10275:24;10271:33;10264:4;10253:9;10249:20;10242:63;;;9776:535;;;;:::o;10828:184::-;10880:77;10877:1;10870:88;10977:4;10974:1;10967:15;11001:4;10998:1;10991:15;11017:380;11107:4;11165:11;11152:25;11255:66;11244:8;11228:14;11224:29;11220:102;11200:18;11196:127;11186:155;;11337:1;11334;11327:12;11186:155;11358:33;;;;;11017:380;-1:-1:-1;;11017:380:1:o;11402:580::-;11479:4;11485:6;11545:11;11532:25;11635:66;11624:8;11608:14;11604:29;11600:102;11580:18;11576:127;11566:155;;11717:1;11714;11707:12;11566:155;11744:33;;11796:20;;;-1:-1:-1;11839:18:1;11828:30;;11825:50;;;11871:1;11868;11861:12;11825:50;11904:4;11892:17;;-1:-1:-1;11935:14:1;11931:27;;;11921:38;;11918:58;;;11972:1;11969;11962:12;11918:58;11402:580;;;;;:::o;11987:271::-;12170:6;12162;12157:3;12144:33;12126:3;12196:16;;12221:13;;;12196:16;11987:271;-1:-1:-1;11987:271:1:o;13287:184::-;13339:77;13336:1;13329:88;13436:4;13433:1;13426:15;13460:4;13457:1;13450:15;13476:175;13544:10;13587;;;13575;;;13571:27;;13610:12;;;13607:38;;;13625:18;;:::i;14063:758::-;14132:5;14180:4;14168:9;14163:3;14159:19;14155:30;14152:50;;;14198:1;14195;14188:12;14152:50;14231:2;14225:9;14273:4;14265:6;14261:17;14344:6;14332:10;14329:22;14308:18;14296:10;14293:34;14290:62;14287:88;;;14355:18;;:::i;:::-;14395:10;14391:2;14384:22;;14424:6;14415:15;;14460:9;14454:16;14501:1;14492:7;14489:14;14479:42;;14517:1;14514;14507:12;14479:42;14530:23;;14598:2;14583:18;;14577:25;14611:32;14577:25;14611:32;:::i;:::-;14671:2;14659:15;;14652:32;14729:2;14714:18;;14708:25;14742:32;14708:25;14742:32;:::i;:::-;14802:2;14790:15;;;;14783:32;14063:758;;-1:-1:-1;;14063:758:1:o;14826:257::-;14925:6;14978:2;14966:9;14957:7;14953:23;14949:32;14946:52;;;14994:1;14991;14984:12;14946:52;15017:60;15069:7;15058:9;15017:60;:::i;15088:386::-;15196:6;15204;15257:3;15245:9;15236:7;15232:23;15228:33;15225:53;;;15274:1;15271;15264:12;15225:53;15306:9;15300:16;15325:31;15350:5;15325:31;:::i;:::-;15375:5;-1:-1:-1;15399:69:1;15460:7;15455:2;15440:18;;15399:69;:::i;:::-;15389:79;;15088:386;;;;;:::o;15818:184::-;15888:6;15941:2;15929:9;15920:7;15916:23;15912:32;15909:52;;;15957:1;15954;15947:12;15909:52;-1:-1:-1;15980:16:1;;15818:184;-1:-1:-1;15818:184:1:o;16007:125::-;16072:9;;;16093:10;;;16090:36;;;16106:18;;:::i;16910:690::-;17233:6;17228:3;17221:19;17270:6;17265:2;17260:3;17256:12;17249:28;17307:6;17302:2;17297:3;17293:12;17286:28;17365:66;17356:6;17352:2;17348:15;17344:88;17339:2;17334:3;17330:12;17323:110;17203:3;17462:6;17456:13;17478:74;17545:6;17539:3;17534;17530:13;17525:2;17517:6;17513:15;17478:74;:::i;:::-;17572:16;;;;17590:3;17568:26;;16910:690;-1:-1:-1;;;;;;16910:690:1:o;18012:184::-;18064:77;18061:1;18054:88;18161:4;18158:1;18151:15;18185:4;18182:1;18175:15;18201:471;18437:66;18428:6;18423:3;18419:16;18415:89;18410:3;18403:102;18385:3;18534:6;18528:13;18550:75;18618:6;18613:2;18608:3;18604:12;18597:4;18589:6;18585:17;18550:75;:::i;:::-;18645:16;;;;18663:2;18641:25;;18201:471;-1:-1:-1;;;18201:471:1:o;19789:128::-;19856:9;;;19877:11;;;19874:37;;;19891:18;;:::i;19922:482::-;20011:1;20054:5;20011:1;20068:330;20089:7;20079:8;20076:21;20068:330;;;20208:4;20140:66;20136:77;20130:4;20127:87;20124:113;;;20217:18;;:::i;:::-;20267:7;20257:8;20253:22;20250:55;;;20287:16;;;;20250:55;20366:22;;;;20326:15;;;;20068:330;;;20072:3;19922:482;;;;;:::o;20409:866::-;20458:5;20488:8;20478:80;;-1:-1:-1;20529:1:1;20543:5;;20478:80;20577:4;20567:76;;-1:-1:-1;20614:1:1;20628:5;;20567:76;20659:4;20677:1;20672:59;;;;20745:1;20740:130;;;;20652:218;;20672:59;20702:1;20693:10;;20716:5;;;20740:130;20777:3;20767:8;20764:17;20761:43;;;20784:18;;:::i;:::-;-1:-1:-1;;20840:1:1;20826:16;;20855:5;;20652:218;;20954:2;20944:8;20941:16;20935:3;20929:4;20926:13;20922:36;20916:2;20906:8;20903:16;20898:2;20892:4;20889:12;20885:35;20882:77;20879:159;;;-1:-1:-1;20991:19:1;;;21023:5;;20879:159;21070:34;21095:8;21089:4;21070:34;:::i;:::-;21200:6;21132:66;21128:79;21119:7;21116:92;21113:118;;;21211:18;;:::i;:::-;21249:20;;20409:866;-1:-1:-1;;;20409:866:1:o;21280:131::-;21340:5;21369:36;21396:8;21390:4;21369:36;:::i","abiDefinition":[{"inputs":[{"internalType":"uint32","name":"synapseDomain_","type":"uint32"},{"internalType":"address","name":"agentManager_","type":"address"},{"internalType":"address","name":"inbox_","type":"address"},{"internalType":"address","name":"gasOracle_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"CallerNotAgentManager","type":"error"},{"inputs":[],"name":"ContentLengthTooBig","type":"error"},{"inputs":[],"name":"EthTransferFailed","type":"error"},{"inputs":[],"name":"FlagOutOfRange","type":"error"},{"inputs":[],"name":"IncorrectDestinationDomain","type":"error"},{"inputs":[],"name":"IncorrectOriginDomain","type":"error"},{"inputs":[],"name":"IncorrectVersionLength","type":"error"},{"inputs":[],"name":"IndexedTooMuch","type":"error"},{"inputs":[],"name":"InsufficientEthBalance","type":"error"},{"inputs":[],"name":"MerkleTreeFull","type":"error"},{"inputs":[],"name":"NotEnoughLeafs","type":"error"},{"inputs":[],"name":"TipsOverflow","type":"error"},{"inputs":[],"name":"TipsValueTooLow","type":"error"},{"inputs":[],"name":"UnallocatedMemory","type":"error"},{"inputs":[],"name":"UnformattedBaseMessage","type":"error"},{"inputs":[],"name":"UnformattedCallData","type":"error"},{"inputs":[],"name":"UnformattedMessage","type":"error"},{"inputs":[],"name":"UnformattedState","type":"error"},{"inputs":[],"name":"ViewOverrun","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"messageHash","type":"bytes32"},{"indexed":true,"internalType":"uint32","name":"nonce","type":"uint32"},{"indexed":true,"internalType":"uint32","name":"destination","type":"uint32"},{"indexed":false,"internalType":"bytes","name":"message","type":"bytes"}],"name":"Sent","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"state","type":"bytes"}],"name":"StateSaved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"actor","type":"address"},{"indexed":false,"internalType":"uint256","name":"tip","type":"uint256"}],"name":"TipWithdrawalCompleted","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"agentManager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"agent","type":"address"}],"name":"agentStatus","outputs":[{"components":[{"internalType":"enum AgentFlag","name":"flag","type":"uint8"},{"internalType":"uint32","name":"domain","type":"uint32"},{"internalType":"uint32","name":"index","type":"uint32"}],"internalType":"struct AgentStatus","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gasOracle","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getAgent","outputs":[{"internalType":"address","name":"agent","type":"address"},{"components":[{"internalType":"enum AgentFlag","name":"flag","type":"uint8"},{"internalType":"uint32","name":"domain","type":"uint32"},{"internalType":"uint32","name":"index","type":"uint32"}],"internalType":"struct AgentStatus","name":"status","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"destination","type":"uint32"},{"internalType":"uint256","name":"paddedRequest","type":"uint256"},{"internalType":"uint256","name":"contentLength","type":"uint256"}],"name":"getMinimumTipsValue","outputs":[{"internalType":"uint256","name":"tipsValue","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"inbox","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"statePayload","type":"bytes"}],"name":"isValidState","outputs":[{"internalType":"bool","name":"isValid","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"agentIndex","type":"uint32"}],"name":"latestDisputeStatus","outputs":[{"components":[{"internalType":"enum DisputeFlag","name":"flag","type":"uint8"},{"internalType":"uint40","name":"openedAt","type":"uint40"},{"internalType":"uint40","name":"resolvedAt","type":"uint40"}],"internalType":"struct DisputeStatus","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"localDomain","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bool","name":"allowFailure","type":"bool"},{"internalType":"bytes","name":"callData","type":"bytes"}],"internalType":"struct MultiCallable.Call[]","name":"calls","type":"tuple[]"}],"name":"multicall","outputs":[{"components":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"bytes","name":"returnData","type":"bytes"}],"internalType":"struct MultiCallable.Result[]","name":"callResults","type":"tuple[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"guardIndex","type":"uint32"},{"internalType":"uint32","name":"notaryIndex","type":"uint32"}],"name":"openDispute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"slashedIndex","type":"uint32"},{"internalType":"uint32","name":"rivalIndex","type":"uint32"}],"name":"resolveDispute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"destination","type":"uint32"},{"internalType":"bytes32","name":"recipient","type":"bytes32"},{"internalType":"uint32","name":"optimisticPeriod","type":"uint32"},{"internalType":"uint256","name":"paddedRequest","type":"uint256"},{"internalType":"bytes","name":"content","type":"bytes"}],"name":"sendBaseMessage","outputs":[{"internalType":"uint32","name":"messageNonce","type":"uint32"},{"internalType":"bytes32","name":"messageHash","type":"bytes32"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint32","name":"destination","type":"uint32"},{"internalType":"uint32","name":"optimisticPeriod","type":"uint32"},{"internalType":"bytes","name":"payload","type":"bytes"}],"name":"sendManagerMessage","outputs":[{"internalType":"uint32","name":"messageNonce","type":"uint32"},{"internalType":"bytes32","name":"messageHash","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"statesAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"suggestLatestState","outputs":[{"internalType":"bytes","name":"stateData","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"nonce","type":"uint32"}],"name":"suggestState","outputs":[{"internalType":"bytes","name":"stateData","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"synapseDomain","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"versionString","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawTips","outputs":[],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"events":{"Sent(bytes32,uint32,uint32,bytes)":{"notice":"Emitted when a new message is sent."},"StateSaved(bytes)":{"notice":"Emitted when a new Origin State is saved after a message was sent."},"TipWithdrawalCompleted(address,uint256)":{"notice":"Emitted when a tip withdrawal is completed."}},"kind":"user","methods":{"agentManager()":{"notice":"Returns the address of the local AgentManager contract, which is treated as the \"source of truth\" for agent statuses."},"agentStatus(address)":{"notice":"Returns (flag, domain, index) for a given agent. See Structures.sol for details."},"getAgent(uint256)":{"notice":"Returns agent address and their current status for a given agent index."},"getMinimumTipsValue(uint32,uint256,uint256)":{"notice":"Returns the minimum tips value for sending a message to a given destination."},"inbox()":{"notice":"Returns the address of the local Inbox contract, which is treated as the \"source of truth\" for agent-signed statements."},"initialize()":{"notice":"Initializes Origin contract: - msg.sender is set as contract owner - State of \"empty merkle tree\" is saved"},"isValidState(bytes)":{"notice":"Check that a given state is valid: matches the historical state of Origin contract. Note: any Agent including an invalid state in their snapshot will be slashed upon providing the snapshot and agent signature for it to Origin contract."},"latestDisputeStatus(uint32)":{"notice":"Returns (flag, openedAt, resolvedAt) that describes the latest status of the latest dispute for an agent with a given index."},"localDomain()":{"notice":"Domain of the local chain, set once upon contract creation"},"multicall((bool,bytes)[])":{"notice":"Aggregates a few calls to this contract into one multicall without modifying `msg.sender`."},"openDispute(uint32,uint32)":{"notice":"Local AgentManager should call this function to indicate that a dispute between a Guard and a Notary has been opened."},"resolveDispute(uint32,uint32)":{"notice":"Local AgentManager should call this function to indicate that a dispute has been resolved due to one of the agents being slashed. \u003e `rivalIndex` will be ZERO, if the slashed agent was not in the Dispute."},"sendBaseMessage(uint32,bytes32,uint32,uint256,bytes)":{"notice":"Send a message to the recipient located on destination domain."},"sendManagerMessage(uint32,uint32,bytes)":{"notice":"Send a manager message to the destination domain."},"statesAmount()":{"notice":"Returns the amount of saved states so far."},"suggestLatestState()":{"notice":"Suggest the data (state after latest sent message) to sign for an Agent. Note: signing the suggested state data will will never lead to slashing of the actor, assuming they have confirmed that the block, which number is included in the data, is not subject to reorganization (which is different for every observed chain)."},"suggestState(uint32)":{"notice":"Given the historical nonce, suggest the state data to sign for an Agent. Note: signing the suggested state data will will never lead to slashing of the actor, assuming they have confirmed that the block, which number is included in the data, is not subject to reorganization (which is different for every observed chain)."},"withdrawTips(address,uint256)":{"notice":"Withdraws locked base message tips to the recipient."}},"notice":"`Origin` contract is used for sending messages to remote chains. It is done by inserting the message hashes into the Origin Merkle, which makes it possible to prove that message was sent using the Merkle proof against the Origin Merkle Root. This essentially compresses the list of messages into a single 32-byte value that needs to be stored on the destination chain. `Origin` is responsible for the following: - Formatting the sent message payloads, and inserting their hashes into the Origin Merkle Tree. - Keeping track of its own historical states (see parent contract `StateHub`). - Enforcing minimum tip values for sent base messages based on the provided execution requests. - Distributing the collected tips upon request from a local `AgentManager` contract.","version":1},"developerDoc":{"kind":"dev","methods":{"acceptOwnership()":{"details":"The new owner accepts the ownership transfer."},"agentStatus(address)":{"details":"Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud, but their status is not updated to Slashed yet.","params":{"agent":"Agent address"},"returns":{"_0":"Status for the given agent: (flag, domain, index)."}},"getAgent(uint256)":{"details":"Will return empty values if agent with given index doesn't exist.","params":{"index":"Agent index in the Agent Merkle Tree"},"returns":{"agent":"   Agent address","status":"  Status for the given agent: (flag, domain, index)"}},"getMinimumTipsValue(uint32,uint256,uint256)":{"details":"Using at least `tipsValue` as `msg.value` for `sendBaseMessage()` will guarantee that the message will be accepted.","params":{"contentLength":"The length of the message content","destination":"Domain of destination chain","paddedRequest":"Padded encoded message execution request on destination chain"},"returns":{"tipsValue":"       Minimum tips value for a message to be accepted"}},"isValidState(bytes)":{"details":"Will revert if any of these is true:  - State payload is not properly formatted.","params":{"statePayload":"Raw payload with state data"},"returns":{"isValid":"         Whether the provided state is valid"}},"latestDisputeStatus(uint32)":{"details":"Will return empty values if agent with given index doesn't exist.","params":{"agentIndex":"Agent index in the Agent Merkle Tree"},"returns":{"_0":"Latest dispute status for the given agent: (flag, openedAt, resolvedAt)"}},"openDispute(uint32,uint32)":{"params":{"guardIndex":"Index of the Guard in the Agent Merkle Tree","notaryIndex":"Index of the Notary in the Agent Merkle Tree"}},"owner()":{"details":"Returns the address of the current owner."},"pendingOwner()":{"details":"Returns the address of the pending owner."},"renounceOwnership()":{"details":"Should be impossible to renounce ownership; we override OpenZeppelin OwnableUpgradeable's implementation of renounceOwnership to make it a no-op"},"resolveDispute(uint32,uint32)":{"params":{"rivalIndex":"Index of the their Dispute Rival in the Agent Merkle Tree","slashedIndex":"Index of the slashed agent in the Agent Merkle Tree"}},"sendBaseMessage(uint32,bytes32,uint32,uint256,bytes)":{"details":"Recipient has to conform to IMessageRecipient interface, otherwise message won't be delivered. Will revert if any of these is true: - `destination` is equal to contract's local domain - `content` length is greater than `MAX_CONTENT_BYTES` - `msg.value` is lower than value of minimum tips for the given message","params":{"content":"Raw bytes content of message","destination":"Domain of destination chain","optimisticPeriod":"Optimistic period for message execution on destination chain","paddedRequest":"Padded encoded message execution request on destination chain","recipient":"Address of recipient on destination chain as bytes32"},"returns":{"messageHash":"         Hash of the sent message","messageNonce":"        Nonce of the sent message"}},"sendManagerMessage(uint32,uint32,bytes)":{"details":"This could only be called by AgentManager, which takes care of encoding the calldata payload. Note: (msgOrigin, proofMaturity) security args will be added to payload on the destination chain so that the AgentManager could verify where the Manager Message came from and how mature is the proof. Note: function is not payable, as no tips are required for sending a manager message. Will revert if `destination` is equal to contract's local domain.","params":{"destination":"Domain of destination chain","optimisticPeriod":"Optimistic period for message execution on destination chain","payload":"Payload for calling AgentManager on destination chain (with extra security args)"}},"statesAmount()":{"details":"This includes the initial state of \"empty Origin Merkle Tree\"."},"suggestLatestState()":{"returns":{"stateData":"    Raw payload with the latest state data"}},"suggestState(uint32)":{"params":{"nonce":"Historical nonce to form a state"},"returns":{"stateData":"    Raw payload with historical state data"}},"transferOwnership(address)":{"details":"Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. Can only be called by the current owner."},"withdrawTips(address,uint256)":{"details":"Could only be called by a local AgentManager.","params":{"amount":"Tips value to withdraw","recipient":"Address to withdraw tips to"}}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"synapseDomain_\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"agentManager_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"inbox_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"gasOracle_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CallerNotAgentManager\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ContentLengthTooBig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EthTransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlagOutOfRange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectDestinationDomain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectOriginDomain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectVersionLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexedTooMuch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientEthBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MerkleTreeFull\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotEnoughLeafs\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TipsOverflow\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TipsValueTooLow\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnallocatedMemory\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnformattedBaseMessage\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnformattedCallData\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnformattedMessage\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnformattedState\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ViewOverrun\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferStarted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"nonce\",\"type\":\"uint32\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"destination\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"}],\"name\":\"Sent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"state\",\"type\":\"bytes\"}],\"name\":\"StateSaved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"actor\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tip\",\"type\":\"uint256\"}],\"name\":\"TipWithdrawalCompleted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"agentManager\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"agent\",\"type\":\"address\"}],\"name\":\"agentStatus\",\"outputs\":[{\"components\":[{\"internalType\":\"enum AgentFlag\",\"name\":\"flag\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"domain\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"index\",\"type\":\"uint32\"}],\"internalType\":\"struct AgentStatus\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gasOracle\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getAgent\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"agent\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"enum AgentFlag\",\"name\":\"flag\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"domain\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"index\",\"type\":\"uint32\"}],\"internalType\":\"struct AgentStatus\",\"name\":\"status\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"destination\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"paddedRequest\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"contentLength\",\"type\":\"uint256\"}],\"name\":\"getMinimumTipsValue\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"tipsValue\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"inbox\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"statePayload\",\"type\":\"bytes\"}],\"name\":\"isValidState\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isValid\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"agentIndex\",\"type\":\"uint32\"}],\"name\":\"latestDisputeStatus\",\"outputs\":[{\"components\":[{\"internalType\":\"enum DisputeFlag\",\"name\":\"flag\",\"type\":\"uint8\"},{\"internalType\":\"uint40\",\"name\":\"openedAt\",\"type\":\"uint40\"},{\"internalType\":\"uint40\",\"name\":\"resolvedAt\",\"type\":\"uint40\"}],\"internalType\":\"struct DisputeStatus\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"localDomain\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"allowFailure\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"struct MultiCallable.Call[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"multicall\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"struct MultiCallable.Result[]\",\"name\":\"callResults\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"guardIndex\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"notaryIndex\",\"type\":\"uint32\"}],\"name\":\"openDispute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"slashedIndex\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"rivalIndex\",\"type\":\"uint32\"}],\"name\":\"resolveDispute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"destination\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"recipient\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"optimisticPeriod\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"paddedRequest\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"content\",\"type\":\"bytes\"}],\"name\":\"sendBaseMessage\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"messageNonce\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"destination\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"optimisticPeriod\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"name\":\"sendManagerMessage\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"messageNonce\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"statesAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"suggestLatestState\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"stateData\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"nonce\",\"type\":\"uint32\"}],\"name\":\"suggestState\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"stateData\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"synapseDomain\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"versionString\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawTips\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"acceptOwnership()\":{\"details\":\"The new owner accepts the ownership transfer.\"},\"agentStatus(address)\":{\"details\":\"Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud, but their status is not updated to Slashed yet.\",\"params\":{\"agent\":\"Agent address\"},\"returns\":{\"_0\":\"Status for the given agent: (flag, domain, index).\"}},\"getAgent(uint256)\":{\"details\":\"Will return empty values if agent with given index doesn't exist.\",\"params\":{\"index\":\"Agent index in the Agent Merkle Tree\"},\"returns\":{\"agent\":\"   Agent address\",\"status\":\"  Status for the given agent: (flag, domain, index)\"}},\"getMinimumTipsValue(uint32,uint256,uint256)\":{\"details\":\"Using at least `tipsValue` as `msg.value` for `sendBaseMessage()` will guarantee that the message will be accepted.\",\"params\":{\"contentLength\":\"The length of the message content\",\"destination\":\"Domain of destination chain\",\"paddedRequest\":\"Padded encoded message execution request on destination chain\"},\"returns\":{\"tipsValue\":\"       Minimum tips value for a message to be accepted\"}},\"isValidState(bytes)\":{\"details\":\"Will revert if any of these is true:  - State payload is not properly formatted.\",\"params\":{\"statePayload\":\"Raw payload with state data\"},\"returns\":{\"isValid\":\"         Whether the provided state is valid\"}},\"latestDisputeStatus(uint32)\":{\"details\":\"Will return empty values if agent with given index doesn't exist.\",\"params\":{\"agentIndex\":\"Agent index in the Agent Merkle Tree\"},\"returns\":{\"_0\":\"Latest dispute status for the given agent: (flag, openedAt, resolvedAt)\"}},\"openDispute(uint32,uint32)\":{\"params\":{\"guardIndex\":\"Index of the Guard in the Agent Merkle Tree\",\"notaryIndex\":\"Index of the Notary in the Agent Merkle Tree\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pendingOwner()\":{\"details\":\"Returns the address of the pending owner.\"},\"renounceOwnership()\":{\"details\":\"Should be impossible to renounce ownership; we override OpenZeppelin OwnableUpgradeable's implementation of renounceOwnership to make it a no-op\"},\"resolveDispute(uint32,uint32)\":{\"params\":{\"rivalIndex\":\"Index of the their Dispute Rival in the Agent Merkle Tree\",\"slashedIndex\":\"Index of the slashed agent in the Agent Merkle Tree\"}},\"sendBaseMessage(uint32,bytes32,uint32,uint256,bytes)\":{\"details\":\"Recipient has to conform to IMessageRecipient interface, otherwise message won't be delivered. Will revert if any of these is true: - `destination` is equal to contract's local domain - `content` length is greater than `MAX_CONTENT_BYTES` - `msg.value` is lower than value of minimum tips for the given message\",\"params\":{\"content\":\"Raw bytes content of message\",\"destination\":\"Domain of destination chain\",\"optimisticPeriod\":\"Optimistic period for message execution on destination chain\",\"paddedRequest\":\"Padded encoded message execution request on destination chain\",\"recipient\":\"Address of recipient on destination chain as bytes32\"},\"returns\":{\"messageHash\":\"         Hash of the sent message\",\"messageNonce\":\"        Nonce of the sent message\"}},\"sendManagerMessage(uint32,uint32,bytes)\":{\"details\":\"This could only be called by AgentManager, which takes care of encoding the calldata payload. Note: (msgOrigin, proofMaturity) security args will be added to payload on the destination chain so that the AgentManager could verify where the Manager Message came from and how mature is the proof. Note: function is not payable, as no tips are required for sending a manager message. Will revert if `destination` is equal to contract's local domain.\",\"params\":{\"destination\":\"Domain of destination chain\",\"optimisticPeriod\":\"Optimistic period for message execution on destination chain\",\"payload\":\"Payload for calling AgentManager on destination chain (with extra security args)\"}},\"statesAmount()\":{\"details\":\"This includes the initial state of \\\"empty Origin Merkle Tree\\\".\"},\"suggestLatestState()\":{\"returns\":{\"stateData\":\"    Raw payload with the latest state data\"}},\"suggestState(uint32)\":{\"params\":{\"nonce\":\"Historical nonce to form a state\"},\"returns\":{\"stateData\":\"    Raw payload with historical state data\"}},\"transferOwnership(address)\":{\"details\":\"Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. Can only be called by the current owner.\"},\"withdrawTips(address,uint256)\":{\"details\":\"Could only be called by a local AgentManager.\",\"params\":{\"amount\":\"Tips value to withdraw\",\"recipient\":\"Address to withdraw tips to\"}}},\"version\":1},\"userdoc\":{\"events\":{\"Sent(bytes32,uint32,uint32,bytes)\":{\"notice\":\"Emitted when a new message is sent.\"},\"StateSaved(bytes)\":{\"notice\":\"Emitted when a new Origin State is saved after a message was sent.\"},\"TipWithdrawalCompleted(address,uint256)\":{\"notice\":\"Emitted when a tip withdrawal is completed.\"}},\"kind\":\"user\",\"methods\":{\"agentManager()\":{\"notice\":\"Returns the address of the local AgentManager contract, which is treated as the \\\"source of truth\\\" for agent statuses.\"},\"agentStatus(address)\":{\"notice\":\"Returns (flag, domain, index) for a given agent. See Structures.sol for details.\"},\"getAgent(uint256)\":{\"notice\":\"Returns agent address and their current status for a given agent index.\"},\"getMinimumTipsValue(uint32,uint256,uint256)\":{\"notice\":\"Returns the minimum tips value for sending a message to a given destination.\"},\"inbox()\":{\"notice\":\"Returns the address of the local Inbox contract, which is treated as the \\\"source of truth\\\" for agent-signed statements.\"},\"initialize()\":{\"notice\":\"Initializes Origin contract: - msg.sender is set as contract owner - State of \\\"empty merkle tree\\\" is saved\"},\"isValidState(bytes)\":{\"notice\":\"Check that a given state is valid: matches the historical state of Origin contract. Note: any Agent including an invalid state in their snapshot will be slashed upon providing the snapshot and agent signature for it to Origin contract.\"},\"latestDisputeStatus(uint32)\":{\"notice\":\"Returns (flag, openedAt, resolvedAt) that describes the latest status of the latest dispute for an agent with a given index.\"},\"localDomain()\":{\"notice\":\"Domain of the local chain, set once upon contract creation\"},\"multicall((bool,bytes)[])\":{\"notice\":\"Aggregates a few calls to this contract into one multicall without modifying `msg.sender`.\"},\"openDispute(uint32,uint32)\":{\"notice\":\"Local AgentManager should call this function to indicate that a dispute between a Guard and a Notary has been opened.\"},\"resolveDispute(uint32,uint32)\":{\"notice\":\"Local AgentManager should call this function to indicate that a dispute has been resolved due to one of the agents being slashed. \u003e `rivalIndex` will be ZERO, if the slashed agent was not in the Dispute.\"},\"sendBaseMessage(uint32,bytes32,uint32,uint256,bytes)\":{\"notice\":\"Send a message to the recipient located on destination domain.\"},\"sendManagerMessage(uint32,uint32,bytes)\":{\"notice\":\"Send a manager message to the destination domain.\"},\"statesAmount()\":{\"notice\":\"Returns the amount of saved states so far.\"},\"suggestLatestState()\":{\"notice\":\"Suggest the data (state after latest sent message) to sign for an Agent. Note: signing the suggested state data will will never lead to slashing of the actor, assuming they have confirmed that the block, which number is included in the data, is not subject to reorganization (which is different for every observed chain).\"},\"suggestState(uint32)\":{\"notice\":\"Given the historical nonce, suggest the state data to sign for an Agent. Note: signing the suggested state data will will never lead to slashing of the actor, assuming they have confirmed that the block, which number is included in the data, is not subject to reorganization (which is different for every observed chain).\"},\"withdrawTips(address,uint256)\":{\"notice\":\"Withdraws locked base message tips to the recipient.\"}},\"notice\":\"`Origin` contract is used for sending messages to remote chains. It is done by inserting the message hashes into the Origin Merkle, which makes it possible to prove that message was sent using the Merkle proof against the Origin Merkle Root. This essentially compresses the list of messages into a single 32-byte value that needs to be stored on the destination chain. `Origin` is responsible for the following: - Formatting the sent message payloads, and inserting their hashes into the Origin Merkle Tree. - Keeping track of its own historical states (see parent contract `StateHub`). - Enforcing minimum tip values for sent base messages based on the provided execution requests. - Distributing the collected tips upon request from a local `AgentManager` contract.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Origin.sol\":\"Origin\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Origin.sol\":{\"keccak256\":\"0x96775924f147f3d1f8df8cdf56731fe52a15af8d8e12e608efb8158c112b18cd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e642a27f5fab3c62b4c02e9754e9e42b1cf2e5381dbea9d3d106d23b7772ebe6\",\"dweb:/ipfs/QmUwn7ZyBvPkjnMuK8ZMSexBUdNQnVtxwyoAyT4DXLQjra\"]}},\"version\":1}"},"hashes":{"acceptOwnership()":"79ba5097","agentManager()":"7622f78d","agentStatus(address)":"28f3fac9","gasOracle()":"5d62a8dd","getAgent(uint256)":"2de5aaf7","getMinimumTipsValue(uint32,uint256,uint256)":"4fc6ad85","inbox()":"fb0e722b","initialize()":"8129fc1c","isValidState(bytes)":"a9dcf22d","latestDisputeStatus(uint32)":"dfadd81a","localDomain()":"8d3638f4","multicall((bool,bytes)[])":"60fc8466","openDispute(uint32,uint32)":"a2155c34","owner()":"8da5cb5b","pendingOwner()":"e30c3978","renounceOwnership()":"715018a6","resolveDispute(uint32,uint32)":"61169218","sendBaseMessage(uint32,bytes32,uint32,uint256,bytes)":"873661bd","sendManagerMessage(uint32,uint32,bytes)":"a1c702a7","statesAmount()":"f2437942","suggestLatestState()":"c0b56f7c","suggestState(uint32)":"b4596b4b","synapseDomain()":"717b8638","transferOwnership(address)":"f2fde38b","version()":"54fd4d50","withdrawTips(address,uint256)":"4e04e7a7"}},"solidity/Origin.sol:OriginEvents":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/OriginEvents.sol\n\n/// @notice A collection of events emitted by the Origin contract\nabstract contract OriginEvents {\n    /**\n     * @notice Emitted when a new message is sent.\n     * @param messageHash   Hash of message; the leaf inserted to the Merkle tree for the message\n     * @param nonce         Nonce of sent message (starts from 1)\n     * @param destination   Destination domain\n     * @param message       Raw bytes of message\n     */\n    event Sent(bytes32 indexed messageHash, uint32 indexed nonce, uint32 indexed destination, bytes message);\n\n    /**\n     * @notice Emitted when a tip withdrawal is completed.\n     * @param actor     Actor address\n     * @param tip       Tip value, denominated in local domain's wei\n     */\n    event TipWithdrawalCompleted(address actor, uint256 tip);\n}\n\n// contracts/events/StateHubEvents.sol\n\n/// @notice A collection of events emitted by the StateHub contract\nabstract contract StateHubEvents {\n    /**\n     * @notice Emitted when a new Origin State is saved after a message was sent.\n     * @param state     Raw payload with state data\n     */\n    event StateSaved(bytes state);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n    /**\n     * @notice Check that a given state is valid: matches the historical state of Origin contract.\n     * Note: any Agent including an invalid state in their snapshot will be slashed\n     * upon providing the snapshot and agent signature for it to Origin contract.\n     * @dev Will revert if any of these is true:\n     *  - State payload is not properly formatted.\n     * @param statePayload      Raw payload with state data\n     * @return isValid          Whether the provided state is valid\n     */\n    function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns the amount of saved states so far.\n     * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n     */\n    function statesAmount() external view returns (uint256);\n\n    /**\n     * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @return statePayload     Raw payload with the latest state data\n     */\n    function suggestLatestState() external view returns (bytes memory statePayload);\n\n    /**\n     * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @param nonce             Historical nonce to form a state\n     * @return statePayload     Raw payload with historical state data\n     */\n    function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/InterfaceGasOracle.sol\n\ninterface InterfaceGasOracle {\n    /**\n     * @notice Fetches the latest gas data for the chain from `Destination` contract,\n     * and uses it to update the oracle values for the requested chain.\n     * @param domain    Domain to update the gas data for\n     */\n    function updateGasData(uint32 domain) external;\n\n    /**\n     * @notice Returns the gas data for the local chain.\n     */\n    function getGasData() external view returns (uint256 paddedGasData);\n\n    /**\n     * @notice Returns the gas data for the given domain, in the decoded format.\n     * @param domain        Domain of chain to get gas data for\n     * @return gasPrice     Gas price for the chain (in Wei per gas unit)\n     * @return dataPrice    Calldata price (in Wei per byte of content)\n     * @return execBuffer   Tx fee safety buffer for message execution (in Wei)\n     * @return amortAttCost Amortized cost for attestation submission (in Wei)\n     * @return etherPrice   Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n     * @return markup       Markup for the message execution (in BWAD)\n     */\n    function getDecodedGasData(uint32 domain)\n        external\n        view\n        returns (\n            uint256 gasPrice,\n            uint256 dataPrice,\n            uint256 execBuffer,\n            uint256 amortAttCost,\n            uint256 etherPrice,\n            uint256 markup\n        );\n\n    /**\n     * @notice Returns the minimum tips for sending a message to a given destination.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return paddedTips       Padded encoded minimum tips information\n     */\n    function getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 paddedTips);\n}\n\n// contracts/interfaces/InterfaceOrigin.sol\n\ninterface InterfaceOrigin {\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /**\n     * @notice Send a message to the recipient located on destination domain.\n     * @dev Recipient has to conform to IMessageRecipient interface, otherwise message won't be delivered.\n     * Will revert if any of these is true:\n     * - `destination` is equal to contract's local domain\n     * - `content` length is greater than `MAX_CONTENT_BYTES`\n     * - `msg.value` is lower than value of minimum tips for the given message\n     * @param destination           Domain of destination chain\n     * @param recipient             Address of recipient on destination chain as bytes32\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param paddedRequest         Padded encoded message execution request on destination chain\n     * @param content               Raw bytes content of message\n     * @return messageNonce         Nonce of the sent message\n     * @return messageHash          Hash of the sent message\n     */\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable returns (uint32 messageNonce, bytes32 messageHash);\n\n    /**\n     * @notice Send a manager message to the destination domain.\n     * @dev This could only be called by AgentManager, which takes care of encoding the calldata payload.\n     * Note: (msgOrigin, proofMaturity) security args will be added to payload on the destination chain\n     * so that the AgentManager could verify where the Manager Message came from and how mature is the proof.\n     * Note: function is not payable, as no tips are required for sending a manager message.\n     * Will revert if `destination` is equal to contract's local domain.\n     * @param destination           Domain of destination chain\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param payload               Payload for calling AgentManager on destination chain (with extra security args)\n     */\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        returns (uint32 messageNonce, bytes32 messageHash);\n\n    // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Withdraws locked base message tips to the recipient.\n     * @dev Could only be called by a local AgentManager.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function withdrawTips(address recipient, uint256 amount) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the minimum tips value for sending a message to a given destination.\n     * @dev Using at least `tipsValue` as `msg.value` for `sendBaseMessage()`\n     * will guarantee that the message will be accepted.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return tipsValue        Minimum tips value for a message to be accepted\n     */\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue);\n}\n\n// contracts/libs/Constants.sol\n\n// Here we define common constants to enable their easier reusing later.\n\n// ══════════════════════════════════ MERKLE ═══════════════════════════════════\n/// @dev Height of the Agent Merkle Tree\nuint256 constant AGENT_TREE_HEIGHT = 32;\n/// @dev Height of the Origin Merkle Tree\nuint256 constant ORIGIN_TREE_HEIGHT = 32;\n/// @dev Height of the Snapshot Merkle Tree. Allows up to 64 leafs, e.g. up to 32 states\nuint256 constant SNAPSHOT_TREE_HEIGHT = 6;\n// ══════════════════════════════════ STRUCTS ══════════════════════════════════\n/// @dev See Attestation.sol: (bytes32,bytes32,uint32,uint40,uint40): 32+32+4+5+5\nuint256 constant ATTESTATION_LENGTH = 78;\n/// @dev See GasData.sol: (uint16,uint16,uint16,uint16,uint16,uint16): 2+2+2+2+2+2\nuint256 constant GAS_DATA_LENGTH = 12;\n/// @dev See Receipt.sol: (uint32,uint32,bytes32,bytes32,uint8,address,address,address): 4+4+32+32+1+20+20+20\nuint256 constant RECEIPT_LENGTH = 133;\n/// @dev See State.sol: (bytes32,uint32,uint32,uint40,uint40,GasData): 32+4+4+5+5+len(GasData)\nuint256 constant STATE_LENGTH = 50 + GAS_DATA_LENGTH;\n/// @dev Maximum amount of states in a single snapshot. Each state produces two leafs in the tree\nuint256 constant SNAPSHOT_MAX_STATES = 1 \u003c\u003c (SNAPSHOT_TREE_HEIGHT - 1);\n// ══════════════════════════════════ MESSAGE ══════════════════════════════════\n/// @dev See Header.sol: (uint8,uint32,uint32,uint32,uint32): 1+4+4+4+4\nuint256 constant HEADER_LENGTH = 17;\n/// @dev See Request.sol: (uint96,uint64,uint32): 12+8+4\nuint256 constant REQUEST_LENGTH = 24;\n/// @dev See Tips.sol: (uint64,uint64,uint64,uint64): 8+8+8+8\nuint256 constant TIPS_LENGTH = 32;\n/// @dev The amount of discarded last bits when encoding tip values\nuint256 constant TIPS_GRANULARITY = 32;\n/// @dev Tip values could be only the multiples of TIPS_MULTIPLIER\nuint256 constant TIPS_MULTIPLIER = 1 \u003c\u003c TIPS_GRANULARITY;\n// ══════════════════════════════ STATEMENT SALTS ══════════════════════════════\n/// @dev Salts for signing various statements\nbytes32 constant ATTESTATION_VALID_SALT = keccak256(\"ATTESTATION_VALID_SALT\");\nbytes32 constant ATTESTATION_INVALID_SALT = keccak256(\"ATTESTATION_INVALID_SALT\");\nbytes32 constant RECEIPT_VALID_SALT = keccak256(\"RECEIPT_VALID_SALT\");\nbytes32 constant RECEIPT_INVALID_SALT = keccak256(\"RECEIPT_INVALID_SALT\");\nbytes32 constant SNAPSHOT_VALID_SALT = keccak256(\"SNAPSHOT_VALID_SALT\");\nbytes32 constant STATE_INVALID_SALT = keccak256(\"STATE_INVALID_SALT\");\n// ═════════════════════════════════ PROTOCOL ══════════════════════════════════\n/// @dev Optimistic period for new agent roots in LightManager\nuint32 constant AGENT_ROOT_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Timeout between the agent root could be proposed and resolved in LightManager\nuint32 constant AGENT_ROOT_PROPOSAL_TIMEOUT = 12 hours;\nuint32 constant BONDING_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Amount of time that the Notary will not be considered active after they won a dispute\nuint32 constant DISPUTE_TIMEOUT_NOTARY = 12 hours;\n/// @dev Amount of time without fresh data from Notaries before contract owner can resolve stuck disputes manually\nuint256 constant FRESH_DATA_TIMEOUT = 4 hours;\n/// @dev Maximum bytes per message = 2 KiB (somewhat arbitrarily set to begin)\nuint256 constant MAX_CONTENT_BYTES = 2 * 2 ** 10;\n/// @dev Maximum value for the summit tip that could be set in GasOracle\nuint256 constant MAX_SUMMIT_TIP = 0.01 ether;\n\n// contracts/libs/Errors.sol\n\n// ══════════════════════════════ INVALID CALLER ═══════════════════════════════\n\nerror CallerNotAgentManager();\nerror CallerNotDestination();\nerror CallerNotInbox();\nerror CallerNotSummit();\n\n// ══════════════════════════════ INCORRECT DATA ═══════════════════════════════\n\nerror IncorrectAttestation();\nerror IncorrectAgentDomain();\nerror IncorrectAgentIndex();\nerror IncorrectAgentProof();\nerror IncorrectAgentRoot();\nerror IncorrectDataHash();\nerror IncorrectDestinationDomain();\nerror IncorrectOriginDomain();\nerror IncorrectSnapshotProof();\nerror IncorrectSnapshotRoot();\nerror IncorrectState();\nerror IncorrectStatesAmount();\nerror IncorrectTipsProof();\nerror IncorrectVersionLength();\n\nerror IncorrectNonce();\nerror IncorrectSender();\nerror IncorrectRecipient();\n\nerror FlagOutOfRange();\nerror IndexOutOfRange();\nerror NonceOutOfRange();\n\nerror OutdatedNonce();\n\nerror UnformattedAttestation();\nerror UnformattedAttestationReport();\nerror UnformattedBaseMessage();\nerror UnformattedCallData();\nerror UnformattedCallDataPrefix();\nerror UnformattedMessage();\nerror UnformattedReceipt();\nerror UnformattedReceiptReport();\nerror UnformattedSignature();\nerror UnformattedSnapshot();\nerror UnformattedState();\nerror UnformattedStateReport();\n\n// ═══════════════════════════════ MERKLE TREES ════════════════════════════════\n\nerror LeafNotProven();\nerror MerkleTreeFull();\nerror NotEnoughLeafs();\nerror TreeHeightTooLow();\n\n// ═════════════════════════════ OPTIMISTIC PERIOD ═════════════════════════════\n\nerror BaseClientOptimisticPeriod();\nerror MessageOptimisticPeriod();\nerror SlashAgentOptimisticPeriod();\nerror WithdrawTipsOptimisticPeriod();\nerror ZeroProofMaturity();\n\n// ═══════════════════════════════ AGENT MANAGER ═══════════════════════════════\n\nerror AgentNotGuard();\nerror AgentNotNotary();\n\nerror AgentCantBeAdded();\nerror AgentNotActive();\nerror AgentNotActiveNorUnstaking();\nerror AgentNotFraudulent();\nerror AgentNotUnstaking();\nerror AgentUnknown();\n\nerror AgentRootNotProposed();\nerror AgentRootTimeoutNotOver();\n\nerror NotStuck();\n\nerror DisputeAlreadyResolved();\nerror DisputeNotOpened();\nerror DisputeTimeoutNotOver();\nerror GuardInDispute();\nerror NotaryInDispute();\n\nerror MustBeSynapseDomain();\nerror SynapseDomainForbidden();\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\nerror AlreadyExecuted();\nerror AlreadyFailed();\nerror DuplicatedSnapshotRoot();\nerror IncorrectMagicValue();\nerror GasLimitTooLow();\nerror GasSuppliedTooLow();\n\n// ══════════════════════════════════ ORIGIN ═══════════════════════════════════\n\nerror ContentLengthTooBig();\nerror EthTransferFailed();\nerror InsufficientEthBalance();\n\n// ════════════════════════════════ GAS ORACLE ═════════════════════════════════\n\nerror LocalGasDataNotSet();\nerror RemoteGasDataNotSet();\n\n// ═══════════════════════════════════ TIPS ════════════════════════════════════\n\nerror SummitTipTooHigh();\nerror TipsClaimMoreThanEarned();\nerror TipsClaimZero();\nerror TipsOverflow();\nerror TipsValueTooLow();\n\n// ════════════════════════════════ MEMORY VIEW ════════════════════════════════\n\nerror IndexedTooMuch();\nerror ViewOverrun();\nerror OccupiedMemory();\nerror UnallocatedMemory();\nerror PrecompileOutOfGas();\n\n// ═════════════════════════════════ MULTICALL ═════════════════════════════════\n\nerror MulticallFailed();\n\n// contracts/libs/TypeCasts.sol\n\nlibrary TypeCasts {\n    // alignment preserving cast\n    function addressToBytes32(address addr) internal pure returns (bytes32) {\n        return bytes32(uint256(uint160(addr)));\n    }\n\n    // alignment preserving cast\n    function bytes32ToAddress(bytes32 buf) internal pure returns (address) {\n        return address(uint160(uint256(buf)));\n    }\n}\n\n// contracts/libs/stack/Number.sol\n\n/// Number is a compact representation of uint256, that is fit into 16 bits\n/// with the maximum relative error under 0.4%.\ntype Number is uint16;\n\nusing NumberLib for Number global;\n\n/// # Number\n/// Library for compact representation of uint256 numbers.\n/// - Number is stored using mantissa and exponent, each occupying 8 bits.\n/// - Numbers under 2**8 are stored as `mantissa` with `exponent = 0xFF`.\n/// - Numbers at least 2**8 are approximated as `(256 + mantissa) \u003c\u003c exponent`\n/// \u003e - `0 \u003c= mantissa \u003c 256`\n/// \u003e - `0 \u003c= exponent \u003c= 247` (`256 * 2**248` doesn't fit into uint256)\n/// # Number stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type  | Bytes |\n/// | ---------- | -------- | ----- | ----- |\n/// | (002..001] | mantissa | uint8 | 1     |\n/// | (001..000] | exponent | uint8 | 1     |\n\nlibrary NumberLib {\n    /// @dev Amount of bits to shift to mantissa field\n    uint16 private constant SHIFT_MANTISSA = 8;\n\n    /// @notice For bwad math (binary wad) we use 2**64 as \"wad\" unit.\n    /// @dev We are using not using 10**18 as wad, because it is not stored precisely in NumberLib.\n    uint256 internal constant BWAD_SHIFT = 64;\n    uint256 internal constant BWAD = 1 \u003c\u003c BWAD_SHIFT;\n    /// @notice ~0.1% in bwad units.\n    uint256 internal constant PER_MILLE_SHIFT = BWAD_SHIFT - 10;\n    uint256 internal constant PER_MILLE = 1 \u003c\u003c PER_MILLE_SHIFT;\n\n    /// @notice Compresses uint256 number into 16 bits.\n    function compress(uint256 value) internal pure returns (Number) {\n        // Find `msb` such as `2**msb \u003c= value \u003c 2**(msb + 1)`\n        uint256 msb = mostSignificantBit(value);\n        // We want to preserve 9 bits of precision.\n        // The highest bit is always 1, so we can skip it.\n        // The remaining 8 highest bits are stored as mantissa.\n        if (msb \u003c 8) {\n            // Value is less than 2**8, so we can use value as mantissa with \"-1\" exponent.\n            return _encode(uint8(value), 0xFF);\n        } else {\n            // We use `msb - 8` as exponent otherwise. Note that `exponent \u003e= 0`.\n            unchecked {\n                uint256 exponent = msb - 8;\n                // Shifting right by `msb-8` bits will shift the \"remaining 8 highest bits\" into the 8 lowest bits.\n                // uint8() will truncate the highest bit.\n                return _encode(uint8(value \u003e\u003e exponent), uint8(exponent));\n            }\n        }\n    }\n\n    /// @notice Decompresses 16 bits number into uint256.\n    /// @dev The outcome is an approximation of the original number: `(value - value / 256) \u003c number \u003c= value`.\n    function decompress(Number number) internal pure returns (uint256 value) {\n        // Isolate 8 highest bits as the mantissa.\n        uint256 mantissa = Number.unwrap(number) \u003e\u003e SHIFT_MANTISSA;\n        // This will truncate the highest bits, leaving only the exponent.\n        uint256 exponent = uint8(Number.unwrap(number));\n        if (exponent == 0xFF) {\n            return mantissa;\n        } else {\n            unchecked {\n                return (256 + mantissa) \u003c\u003c (exponent);\n            }\n        }\n    }\n\n    /// @dev Returns the most significant bit of `x`\n    /// https://solidity-by-example.org/bitwise/\n    function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\n        // To find `msb` we determine it bit by bit, starting from the highest one.\n        // `0 \u003c= msb \u003c= 255`, so we start from the highest bit, 1\u003c\u003c7 == 128.\n        // If `x` is at least 2**128, then the highest bit of `x` is at least 128.\n        // solhint-disable no-inline-assembly\n        assembly {\n            // `f` is set to 1\u003c\u003c7 if `x \u003e= 2**128` and to 0 otherwise.\n            let f := shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\n            // If `x \u003e= 2**128` then set `msb` highest bit to 1 and shift `x` right by 128.\n            // Otherwise, `msb` remains 0 and `x` remains unchanged.\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        // `x` is now at most 2**128 - 1. Continue the same way, the next highest bit is 1\u003c\u003c6 == 64.\n        assembly {\n            // `f` is set to 1\u003c\u003c6 if `x \u003e= 2**64` and to 0 otherwise.\n            let f := shl(6, gt(x, 0xFFFFFFFFFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c5 if `x \u003e= 2**32` and to 0 otherwise.\n            let f := shl(5, gt(x, 0xFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c4 if `x \u003e= 2**16` and to 0 otherwise.\n            let f := shl(4, gt(x, 0xFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c3 if `x \u003e= 2**8` and to 0 otherwise.\n            let f := shl(3, gt(x, 0xFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c2 if `x \u003e= 2**4` and to 0 otherwise.\n            let f := shl(2, gt(x, 0xF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c1 if `x \u003e= 2**2` and to 0 otherwise.\n            let f := shl(1, gt(x, 0x3))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1 if `x \u003e= 2**1` and to 0 otherwise.\n            let f := gt(x, 0x1)\n            msb := or(msb, f)\n        }\n    }\n\n    /// @dev Wraps (mantissa, exponent) pair into Number.\n    function _encode(uint8 mantissa, uint8 exponent) private pure returns (Number) {\n        // Casts below are upcasts, so they are safe.\n        return Number.wrap(uint16(mantissa) \u003c\u003c SHIFT_MANTISSA | uint16(exponent));\n    }\n}\n\n// contracts/libs/stack/Request.sol\n\n/// Request is encoded data with \"message execution request\".\ntype Request is uint192;\n\nusing RequestLib for Request global;\n\n/// Library for formatting _the request part_ of _the base messages_.\n/// - Request represents a message sender requirements for the message execution on the destination chain.\n/// - Request occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n/// \u003e gasDrop field is included for future compatibility and is ignored at the moment.\n///\n/// # Request stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type   | Bytes | Description                                          |\n/// | ---------- | -------- | ------ | ----- | ---------------------------------------------------- |\n/// | (024..012] | gasDrop  | uint96 | 12    | Minimum amount of gas token to drop to the recipient |\n/// | (012..004] | gasLimit | uint64 | 8     | Minimum amount of gas units to supply for execution  |\n/// | (004..000] | version  | uint32 | 4     | Base message version to pass to the recipient        |\n\nlibrary RequestLib {\n    /// @dev Amount of bits to shift to gasDrop field\n    uint192 private constant SHIFT_GAS_DROP = 12 * 8;\n    /// @dev Amount of bits to shift to gasLimit field\n    uint192 private constant SHIFT_GAS_LIMIT = 4 * 8;\n\n    /// @notice Returns an encoded request with the given fields\n    /// @param gasDrop_     Minimum amount of gas token to drop to the recipient (ignored at the moment)\n    /// @param gasLimit_    Minimum amount of gas units to supply for execution\n    /// @param version_     Base message version to pass to the recipient\n    function encodeRequest(uint96 gasDrop_, uint64 gasLimit_, uint32 version_) internal pure returns (Request) {\n        // Casts below are upcasts, so they are safe\n        return Request.wrap(uint192(gasDrop_) \u003c\u003c SHIFT_GAS_DROP | uint192(gasLimit_) \u003c\u003c SHIFT_GAS_LIMIT | version_);\n    }\n\n    /// @notice Wraps the padded encoded request into a Request-typed value.\n    /// @dev The \"padded\" request is simply an encoded request casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded requests\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedRequest) internal pure returns (Request) {\n        // Casting to uint192 will truncate the highest bits, which is the behavior we want\n        return Request.wrap(uint192(paddedRequest));\n    }\n\n    /// @notice Returns the requested of gas token to drop to the recipient.\n    function gasDrop(Request request) internal pure returns (uint96) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return uint96(Request.unwrap(request) \u003e\u003e SHIFT_GAS_DROP);\n    }\n\n    /// @notice Returns the requested minimum amount of gas units to supply for execution.\n    function gasLimit(Request request) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Request.unwrap(request) \u003e\u003e SHIFT_GAS_LIMIT);\n    }\n\n    /// @notice Returns the requested base message version to pass to the recipient.\n    function version(Request request) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Request.unwrap(request));\n    }\n}\n\n// node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        require(value \u003c= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        require(value \u003c= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        require(value \u003c= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value \u003c= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        require(value \u003c= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        require(value \u003c= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        require(value \u003c= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        require(value \u003c= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        require(value \u003c= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        require(value \u003c= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        require(value \u003c= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        require(value \u003c= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        require(value \u003c= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        require(value \u003c= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        require(value \u003c= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value \u003c= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        require(value \u003c= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        require(value \u003c= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        require(value \u003c= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value \u003c= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        require(value \u003c= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        require(value \u003c= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        require(value \u003c= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value \u003c= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        require(value \u003c= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        require(value \u003c= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        require(value \u003c= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value \u003c= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        require(value \u003c= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value \u003c= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value \u003c= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     *\n     * _Available since v3.0._\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value \u003e= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     *\n     * _Available since v3.0._\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value \u003c= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     *\n     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length \u003e 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance \u003e= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance \u003e= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length \u003e 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n\n// contracts/base/MultiCallable.sol\n\n/// @notice Collection of Multicall utilities. Fork of Multicall3:\n/// https://github.com/mds1/multicall/blob/master/src/Multicall3.sol\nabstract contract MultiCallable {\n    struct Call {\n        bool allowFailure;\n        bytes callData;\n    }\n\n    struct Result {\n        bool success;\n        bytes returnData;\n    }\n\n    /// @notice Aggregates a few calls to this contract into one multicall without modifying `msg.sender`.\n    function multicall(Call[] calldata calls) external returns (Result[] memory callResults) {\n        uint256 amount = calls.length;\n        callResults = new Result[](amount);\n        Call calldata call_;\n        for (uint256 i = 0; i \u003c amount;) {\n            call_ = calls[i];\n            Result memory result = callResults[i];\n            // We perform a delegate call to ourselves here. Delegate call does not modify `msg.sender`, so\n            // this will have the same effect as if `msg.sender` performed all the calls themselves one by one.\n            // solhint-disable-next-line avoid-low-level-calls\n            (result.success, result.returnData) = address(this).delegatecall(call_.callData);\n            // solhint-disable-next-line no-inline-assembly\n            assembly {\n                // Revert if the call fails and failure is not allowed\n                // `allowFailure := calldataload(call_)` and `success := mload(result)`\n                if iszero(or(calldataload(call_), mload(result))) {\n                    // Revert with `0x4d6a2328` (function selector for `MulticallFailed()`)\n                    mstore(0x00, 0x4d6a232800000000000000000000000000000000000000000000000000000000)\n                    revert(0x00, 0x04)\n                }\n            }\n            unchecked {\n                ++i;\n            }\n        }\n    }\n}\n\n// contracts/base/Version.sol\n\n/**\n * @title Versioned\n * @notice Version getter for contracts. Doesn't use any storage slots, meaning\n * it will never cause any troubles with the upgradeable contracts. For instance, this contract\n * can be added or removed from the inheritance chain without shifting the storage layout.\n */\nabstract contract Versioned {\n    /**\n     * @notice Struct that is mimicking the storage layout of a string with 32 bytes or less.\n     * Length is limited by 32, so the whole string payload takes two memory words:\n     * @param length    String length\n     * @param data      String characters\n     */\n    struct _ShortString {\n        uint256 length;\n        bytes32 data;\n    }\n\n    /// @dev Length of the \"version string\"\n    uint256 private immutable _length;\n    /// @dev Bytes representation of the \"version string\".\n    /// Strings with length over 32 are not supported!\n    bytes32 private immutable _data;\n\n    constructor(string memory version_) {\n        _length = bytes(version_).length;\n        if (_length \u003e 32) revert IncorrectVersionLength();\n        // bytes32 is left-aligned =\u003e this will store the byte representation of the string\n        // with the trailing zeroes to complete the 32-byte word\n        _data = bytes32(bytes(version_));\n    }\n\n    function version() external view returns (string memory versionString) {\n        // Load the immutable values to form the version string\n        _ShortString memory str = _ShortString(_length, _data);\n        // The only way to do this cast is doing some dirty assembly\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            versionString := str\n        }\n    }\n}\n\n// contracts/libs/ChainContext.sol\n\n/// @notice Library for accessing chain context variables as tightly packed integers.\n/// Messaging contracts should rely on this library for accessing chain context variables\n/// instead of doing the casting themselves.\nlibrary ChainContext {\n    using SafeCast for uint256;\n\n    /// @notice Returns the current block number as uint40.\n    /// @dev Reverts if block number is greater than 40 bits, which is not supposed to happen\n    /// until the block.timestamp overflows (assuming block time is at least 1 second).\n    function blockNumber() internal view returns (uint40) {\n        return block.number.toUint40();\n    }\n\n    /// @notice Returns the current block timestamp as uint40.\n    /// @dev Reverts if block timestamp is greater than 40 bits, which is\n    /// supposed to happen approximately in year 36835.\n    function blockTimestamp() internal view returns (uint40) {\n        return block.timestamp.toUint40();\n    }\n\n    /// @notice Returns the chain id as uint32.\n    /// @dev Reverts if chain id is greater than 32 bits, which is not\n    /// supposed to happen in production.\n    function chainId() internal view returns (uint32) {\n        return block.chainid.toUint32();\n    }\n}\n\n// contracts/libs/Structures.sol\n\n// Here we define common enums and structures to enable their easier reusing later.\n\n// ═══════════════════════════════ AGENT STATUS ════════════════════════════════\n\n/// @dev Potential statuses for the off-chain bonded agent:\n/// - Unknown: never provided a bond =\u003e signature not valid\n/// - Active: has a bond in BondingManager =\u003e signature valid\n/// - Unstaking: has a bond in BondingManager, initiated the unstaking =\u003e signature not valid\n/// - Resting: used to have a bond in BondingManager, successfully unstaked =\u003e signature not valid\n/// - Fraudulent: proven to commit fraud, value in Merkle Tree not updated =\u003e signature not valid\n/// - Slashed: proven to commit fraud, value in Merkle Tree was updated =\u003e signature not valid\n/// Unstaked agent could later be added back to THE SAME domain by staking a bond again.\n/// Honest agent: Unknown -\u003e Active -\u003e unstaking -\u003e Resting -\u003e Active ...\n/// Malicious agent: Unknown -\u003e Active -\u003e Fraudulent -\u003e Slashed\n/// Malicious agent: Unknown -\u003e Active -\u003e Unstaking -\u003e Fraudulent -\u003e Slashed\nenum AgentFlag {\n    Unknown,\n    Active,\n    Unstaking,\n    Resting,\n    Fraudulent,\n    Slashed\n}\n\n/// @notice Struct for storing an agent in the BondingManager contract.\nstruct AgentStatus {\n    AgentFlag flag;\n    uint32 domain;\n    uint32 index;\n}\n// 184 bits available for tight packing\n\nusing StructureUtils for AgentStatus global;\n\n/// @notice Potential statuses of an agent in terms of being in dispute\n/// - None: agent is not in dispute\n/// - Pending: agent is in unresolved dispute\n/// - Slashed: agent was in dispute that lead to agent being slashed\n/// Note: agent who won the dispute has their status reset to None\nenum DisputeFlag {\n    None,\n    Pending,\n    Slashed\n}\n\n/// @notice Struct for storing dispute status of an agent.\n/// @param flag         Dispute flag: None/Pending/Slashed.\n/// @param openedAt     Timestamp when the latest agent dispute was opened (zero if not opened).\n/// @param resolvedAt   Timestamp when the latest agent dispute was resolved (zero if not resolved).\nstruct DisputeStatus {\n    DisputeFlag flag;\n    uint40 openedAt;\n    uint40 resolvedAt;\n}\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\n/// @notice Struct representing the status of Destination contract.\n/// @param snapRootTime     Timestamp when latest snapshot root was accepted\n/// @param agentRootTime    Timestamp when latest agent root was accepted\n/// @param notaryIndex      Index of Notary who signed the latest agent root\nstruct DestinationStatus {\n    uint40 snapRootTime;\n    uint40 agentRootTime;\n    uint32 notaryIndex;\n}\n\n// ═══════════════════════════════ EXECUTION HUB ═══════════════════════════════\n\n/// @notice Potential statuses of the message in Execution Hub.\n/// - None: there hasn't been a valid attempt to execute the message yet\n/// - Failed: there was a valid attempt to execute the message, but recipient reverted\n/// - Success: there was a valid attempt to execute the message, and recipient did not revert\n/// Note: message can be executed until its status is Success\nenum MessageStatus {\n    None,\n    Failed,\n    Success\n}\n\nlibrary StructureUtils {\n    /// @notice Checks that Agent is Active\n    function verifyActive(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active) {\n            revert AgentNotActive();\n        }\n    }\n\n    /// @notice Checks that Agent is Unstaking\n    function verifyUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Unstaking) {\n            revert AgentNotUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Active or Unstaking\n    function verifyActiveUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active \u0026\u0026 status.flag != AgentFlag.Unstaking) {\n            revert AgentNotActiveNorUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Fraudulent\n    function verifyFraudulent(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Fraudulent) {\n            revert AgentNotFraudulent();\n        }\n    }\n\n    /// @notice Checks that Agent is not Unknown\n    function verifyKnown(AgentStatus memory status) internal pure {\n        if (status.flag == AgentFlag.Unknown) {\n            revert AgentUnknown();\n        }\n    }\n}\n\n// contracts/libs/memory/MemView.sol\n\n/// @dev MemView is an untyped view over a portion of memory to be used instead of `bytes memory`\ntype MemView is uint256;\n\n/// @dev Attach library functions to MemView\nusing MemViewLib for MemView global;\n\n/// @notice Library for operations with the memory views.\n/// Forked from https://github.com/summa-tx/memview-sol with several breaking changes:\n/// - The codebase is ported to Solidity 0.8\n/// - Custom errors are added\n/// - The runtime type checking is replaced with compile-time check provided by User-Defined Value Types\n///   https://docs.soliditylang.org/en/latest/types.html#user-defined-value-types\n/// - uint256 is used as the underlying type for the \"memory view\" instead of bytes29.\n///   It is wrapped into MemView custom type in order not to be confused with actual integers.\n/// - Therefore the \"type\" field is discarded, allowing to allocate 16 bytes for both view location and length\n/// - The documentation is expanded\n/// - Library functions unused by the rest of the codebase are removed\n//  - Very pretty code separators are added :)\nlibrary MemViewLib {\n    /// @notice Stack layout for uint256 (from highest bits to lowest)\n    /// (32 .. 16]      loc     16 bytes    Memory address of underlying bytes\n    /// (16 .. 00]      len     16 bytes    Length of underlying bytes\n\n    // ═══════════════════════════════════════════ BUILDING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Instantiate a new untyped memory view. This should generally not be called directly.\n     * Prefer `ref` wherever possible.\n     * @param loc_          The memory address\n     * @param len_          The length\n     * @return The new view with the specified location and length\n     */\n    function build(uint256 loc_, uint256 len_) internal pure returns (MemView) {\n        uint256 end_ = loc_ + len_;\n        // Make sure that a view is not constructed that points to unallocated memory\n        // as this could be indicative of a buffer overflow attack\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            if gt(end_, mload(0x40)) { end_ := 0 }\n        }\n        if (end_ == 0) {\n            revert UnallocatedMemory();\n        }\n        return _unsafeBuildUnchecked(loc_, len_);\n    }\n\n    /**\n     * @notice Instantiate a memory view from a byte array.\n     * @dev Note that due to Solidity memory representation, it is not possible to\n     * implement a deref, as the `bytes` type stores its len in memory.\n     * @param arr           The byte array\n     * @return The memory view over the provided byte array\n     */\n    function ref(bytes memory arr) internal pure returns (MemView) {\n        uint256 len_ = arr.length;\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 loc_;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // We add 0x20, so that the view starts exactly where the array data starts\n            loc_ := add(arr, 0x20)\n        }\n        return build(loc_, len_);\n    }\n\n    // ════════════════════════════════════════════ CLONING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to the new memory.\n     * @param memView       The memory view\n     * @return arr          The cloned byte array\n     */\n    function clone(MemView memView) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        unchecked {\n            _unsafeCopyTo(memView, ptr + 0x20);\n        }\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 len_ = memView.len();\n        uint256 footprint_ = memView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    /**\n     * @notice Copies all views, joins them into a new bytearray.\n     * @param memViews      The memory views\n     * @return arr          The new byte array with joined data behind the given views\n     */\n    function join(MemView[] memory memViews) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        MemView newView;\n        unchecked {\n            newView = _unsafeJoin(memViews, ptr + 0x20);\n        }\n        uint256 len_ = newView.len();\n        uint256 footprint_ = newView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    // ══════════════════════════════════════════ INSPECTING MEMORY VIEW ═══════════════════════════════════════════════\n\n    /**\n     * @notice Returns the memory address of the underlying bytes.\n     * @param memView       The memory view\n     * @return loc_         The memory address\n     */\n    function loc(MemView memView) internal pure returns (uint256 loc_) {\n        // loc is stored in the highest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u003e\u003e 128;\n    }\n\n    /**\n     * @notice Returns the number of bytes of the view.\n     * @param memView       The memory view\n     * @return len_         The length of the view\n     */\n    function len(MemView memView) internal pure returns (uint256 len_) {\n        // len is stored in the lowest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u0026 type(uint128).max;\n    }\n\n    /**\n     * @notice Returns the endpoint of `memView`.\n     * @param memView       The memory view\n     * @return end_         The endpoint of `memView`\n     */\n    function end(MemView memView) internal pure returns (uint256 end_) {\n        // The endpoint never overflows uint128, let alone uint256, so we could use unchecked math here\n        unchecked {\n            return memView.loc() + memView.len();\n        }\n    }\n\n    /**\n     * @notice Returns the number of memory words this memory view occupies, rounded up.\n     * @param memView       The memory view\n     * @return words_       The number of memory words\n     */\n    function words(MemView memView) internal pure returns (uint256 words_) {\n        // returning ceil(length / 32.0)\n        unchecked {\n            return (memView.len() + 31) \u003e\u003e 5;\n        }\n    }\n\n    /**\n     * @notice Returns the in-memory footprint of a fresh copy of the view.\n     * @param memView       The memory view\n     * @return footprint_   The in-memory footprint of a fresh copy of the view.\n     */\n    function footprint(MemView memView) internal pure returns (uint256 footprint_) {\n        // words() * 32\n        return memView.words() \u003c\u003c 5;\n    }\n\n    // ════════════════════════════════════════════ HASHING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the keccak256 hash of the underlying memory\n     * @param memView       The memory view\n     * @return digest       The keccak256 hash of the underlying memory\n     */\n    function keccak(MemView memView) internal pure returns (bytes32 digest) {\n        uint256 loc_ = memView.loc();\n        uint256 len_ = memView.len();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            digest := keccak256(loc_, len_)\n        }\n    }\n\n    /**\n     * @notice Adds a salt to the keccak256 hash of the underlying data and returns the keccak256 hash of the\n     * resulting data.\n     * @param memView       The memory view\n     * @return digestSalted keccak256(salt, keccak256(memView))\n     */\n    function keccakSalted(MemView memView, bytes32 salt) internal pure returns (bytes32 digestSalted) {\n        return keccak256(bytes.concat(salt, memView.keccak()));\n    }\n\n    // ════════════════════════════════════════════ SLICING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Safe slicing without memory modification.\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the given index\n     */\n    function slice(MemView memView, uint256 index_, uint256 len_) internal pure returns (MemView) {\n        uint256 loc_ = memView.loc();\n        // Ensure it doesn't overrun the view\n        if (loc_ + index_ + len_ \u003e memView.end()) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // loc_ + index_ \u003c= memView.end()\n            return build({loc_: loc_ + index_, len_: len_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing bytes from `index` to end(memView).\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @return The new view for the slice starting from the given index until the initial view endpoint\n     */\n    function sliceFrom(MemView memView, uint256 index_) internal pure returns (MemView) {\n        uint256 len_ = memView.len();\n        // Ensure it doesn't overrun the view\n        if (index_ \u003e len_) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // index_ \u003c= len_ =\u003e memView.loc() + index_ \u003c= memView.loc() + memView.len() == memView.end()\n            return build({loc_: memView.loc() + index_, len_: len_ - index_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the first `len` bytes.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the initial view beginning\n     */\n    function prefix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        return memView.slice({index_: 0, len_: len_});\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the last `len` byte.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length until the initial view endpoint\n     */\n    function postfix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        uint256 viewLen = memView.len();\n        // Ensure it doesn't overrun the view\n        if (len_ \u003e viewLen) {\n            revert ViewOverrun();\n        }\n        // Could do the unchecked math due to the check above\n        uint256 index_;\n        unchecked {\n            index_ = viewLen - len_;\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // len_ \u003c= memView.len() =\u003e memView.loc() \u003c= loc_ \u003c= memView.end()\n            return build({loc_: memView.loc() + viewLen - len_, len_: len_});\n        }\n    }\n\n    // ═══════════════════════════════════════════ INDEXING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Load up to 32 bytes from the view onto the stack.\n     * @dev Returns a bytes32 with only the `bytes_` HIGHEST bytes set.\n     * This can be immediately cast to a smaller fixed-length byte array.\n     * To automatically cast to an integer, use `indexUint`.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return result       The 32 byte result having only `bytes_` highest bytes set\n     */\n    function index(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (bytes32 result) {\n        if (bytes_ == 0) {\n            return bytes32(0);\n        }\n        // Can't load more than 32 bytes to the stack in one go\n        if (bytes_ \u003e 32) {\n            revert IndexedTooMuch();\n        }\n        // The last indexed byte should be within view boundaries\n        if (index_ + bytes_ \u003e memView.len()) {\n            revert ViewOverrun();\n        }\n        uint256 bitLength = bytes_ \u003c\u003c 3; // bytes_ * 8\n        uint256 loc_ = memView.loc();\n        // Get a mask with `bitLength` highest bits set\n        uint256 mask;\n        // 0x800...00 binary representation is 100...00\n        // sar stands for \"signed arithmetic shift\": https://en.wikipedia.org/wiki/Arithmetic_shift\n        // sar(N-1, 100...00) = 11...100..00, with exactly N highest bits set to 1\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            mask := sar(sub(bitLength, 1), 0x8000000000000000000000000000000000000000000000000000000000000000)\n        }\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load a full word using index offset, and apply mask to ignore non-relevant bytes\n            result := and(mload(add(loc_, index_)), mask)\n        }\n    }\n\n    /**\n     * @notice Parse an unsigned integer from the view at `index`.\n     * @dev Requires that the view have \u003e= `bytes_` bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return The unsigned integer\n     */\n    function indexUint(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (uint256) {\n        bytes32 indexedBytes = memView.index(index_, bytes_);\n        // `index()` returns left-aligned `bytes_`, while integers are right-aligned\n        // Shifting here to right-align with the full 32 bytes word: need to shift right `(32 - bytes_)` bytes\n        unchecked {\n            // memView.index() reverts when bytes_ \u003e 32, thus unchecked math\n            return uint256(indexedBytes) \u003e\u003e ((32 - bytes_) \u003c\u003c 3);\n        }\n    }\n\n    /**\n     * @notice Parse an address from the view at `index`.\n     * @dev Requires that the view have \u003e= 20 bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @return The address\n     */\n    function indexAddress(MemView memView, uint256 index_) internal pure returns (address) {\n        // index 20 bytes as `uint160`, and then cast to `address`\n        return address(uint160(memView.indexUint(index_, 20)));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns a memory view over the specified memory location\n    /// without checking if it points to unallocated memory.\n    function _unsafeBuildUnchecked(uint256 loc_, uint256 len_) private pure returns (MemView) {\n        // There is no scenario where loc or len would overflow uint128, so we omit this check.\n        // We use the highest 128 bits to encode the location and the lowest 128 bits to encode the length.\n        return MemView.wrap((loc_ \u003c\u003c 128) | len_);\n    }\n\n    /**\n     * @notice Copy the view to a location, return an unsafe memory reference\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memView       The memory view\n     * @param newLoc        The new location to copy the underlying view data\n     * @return The memory view over the unsafe memory with the copied underlying data\n     */\n    function _unsafeCopyTo(MemView memView, uint256 newLoc) private view returns (MemView) {\n        uint256 len_ = memView.len();\n        uint256 oldLoc = memView.loc();\n\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (newLoc \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        bool res;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // use the identity precompile (0x04) to copy\n            res := staticcall(gas(), 0x04, oldLoc, len_, newLoc, len_)\n        }\n        if (!res) revert PrecompileOutOfGas();\n        return _unsafeBuildUnchecked({loc_: newLoc, len_: len_});\n    }\n\n    /**\n     * @notice Join the views in memory, return an unsafe reference to the memory.\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memViews      The memory views\n     * @return The conjoined view pointing to the new memory\n     */\n    function _unsafeJoin(MemView[] memory memViews, uint256 location) private view returns (MemView) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (location \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        // Copy the views to the specified location one by one, by tracking the amount of copied bytes so far\n        uint256 offset = 0;\n        for (uint256 i = 0; i \u003c memViews.length;) {\n            MemView memView = memViews[i];\n            // We can use the unchecked math here as location + sum(view.length) will never overflow uint256\n            unchecked {\n                _unsafeCopyTo(memView, location + offset);\n                offset += memView.len();\n                ++i;\n            }\n        }\n        return _unsafeBuildUnchecked({loc_: location, len_: offset});\n    }\n}\n\n// contracts/libs/merkle/MerkleMath.sol\n\nlibrary MerkleMath {\n    // ═════════════════════════════════════════ BASIC MERKLE CALCULATIONS ═════════════════════════════════════════════\n\n    /**\n     * @notice Calculates the merkle root for the given leaf and merkle proof.\n     * @dev Will revert if proof length exceeds the tree height.\n     * @param index     Index of `leaf` in tree\n     * @param leaf      Leaf of the merkle tree\n     * @param proof     Proof of inclusion of `leaf` in the tree\n     * @param height    Height of the merkle tree\n     * @return root_    Calculated Merkle Root\n     */\n    function proofRoot(uint256 index, bytes32 leaf, bytes32[] memory proof, uint256 height)\n        internal\n        pure\n        returns (bytes32 root_)\n    {\n        // Proof length could not exceed the tree height\n        uint256 proofLen = proof.length;\n        if (proofLen \u003e height) revert TreeHeightTooLow();\n        root_ = leaf;\n        /// @dev Apply unchecked to all ++h operations\n        unchecked {\n            // Go up the tree levels from the leaf following the proof\n            for (uint256 h = 0; h \u003c proofLen; ++h) {\n                // Get a sibling node on current level: this is proof[h]\n                root_ = getParent(root_, proof[h], index, h);\n            }\n            // Go up to the root: the remaining siblings are EMPTY\n            for (uint256 h = proofLen; h \u003c height; ++h) {\n                root_ = getParent(root_, bytes32(0), index, h);\n            }\n        }\n    }\n\n    /**\n     * @notice Calculates the parent of a node on the path from one of the leafs to root.\n     * @param node          Node on a path from tree leaf to root\n     * @param sibling       Sibling for a given node\n     * @param leafIndex     Index of the tree leaf\n     * @param nodeHeight    \"Level height\" for `node` (ZERO for leafs, ORIGIN_TREE_HEIGHT for root)\n     */\n    function getParent(bytes32 node, bytes32 sibling, uint256 leafIndex, uint256 nodeHeight)\n        internal\n        pure\n        returns (bytes32 parent)\n    {\n        // Index for `node` on its \"tree level\" is (leafIndex / 2**height)\n        // \"Left child\" has even index, \"right child\" has odd index\n        if ((leafIndex \u003e\u003e nodeHeight) \u0026 1 == 0) {\n            // Left child\n            return getParent(node, sibling);\n        } else {\n            // Right child\n            return getParent(sibling, node);\n        }\n    }\n\n    /// @notice Calculates the parent of tow nodes in the merkle tree.\n    /// @dev We use implementation with H(0,0) = 0\n    /// This makes EVERY empty node in the tree equal to ZERO,\n    /// saving us from storing H(0,0), H(H(0,0), H(0, 0)), and so on\n    /// @param leftChild    Left child of the calculated node\n    /// @param rightChild   Right child of the calculated node\n    /// @return parent      Value for the node having above mentioned children\n    function getParent(bytes32 leftChild, bytes32 rightChild) internal pure returns (bytes32 parent) {\n        if (leftChild == bytes32(0) \u0026\u0026 rightChild == bytes32(0)) {\n            return 0;\n        } else {\n            return keccak256(bytes.concat(leftChild, rightChild));\n        }\n    }\n\n    // ════════════════════════════════ ROOT/PROOF CALCULATION FOR A LIST OF LEAFS ═════════════════════════════════════\n\n    /**\n     * @notice Calculates merkle root for a list of given leafs.\n     * Merkle Tree is constructed by padding the list with ZERO values for leafs until list length is `2**height`.\n     * Merkle Root is calculated for the constructed tree, and then saved in `leafs[0]`.\n     * \u003e Note:\n     * \u003e - `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * \u003e - Caller is expected not to reuse `hashes` list after the call, and only use `leafs[0]` value,\n     * which is guaranteed to contain the calculated merkle root.\n     * \u003e - root is calculated using the `H(0,0) = 0` Merkle Tree implementation. See MerkleTree.sol for details.\n     * @dev Amount of leaves should be at most `2**height`\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param height    Height of the Merkle Tree to construct\n     */\n    function calculateRoot(bytes32[] memory hashes, uint256 height) internal pure {\n        uint256 levelLength = hashes.length;\n        // Amount of hashes could not exceed amount of leafs in tree with the given height\n        if (levelLength \u003e (1 \u003c\u003c height)) revert TreeHeightTooLow();\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\": the amount of iterations for the for loop above.\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n            }\n        }\n    }\n\n    /**\n     * @notice Generates a proof of inclusion of a leaf in the list. If the requested index is outside\n     * of the list range, generates a proof of inclusion for an empty leaf (proof of non-inclusion).\n     * The Merkle Tree is constructed by padding the list with ZERO values until list length is a power of two\n     * __AND__ index is in the extended list range. For example:\n     *  - `hashes.length == 6` and `0 \u003c= index \u003c= 7` will \"extend\" the list to 8 entries.\n     *  - `hashes.length == 6` and `7 \u003c index \u003c= 15` will \"extend\" the list to 16 entries.\n     * \u003e Note: `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * Caller is expected not to reuse `hashes` list after the call.\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param index     Leaf index to generate the proof for\n     * @return proof    Generated merkle proof\n     */\n    function calculateProof(bytes32[] memory hashes, uint256 index) internal pure returns (bytes32[] memory proof) {\n        // Use only meaningful values for the shortened proof\n        // Check if index is within the list range (we want to generates proofs for outside leafs as well)\n        uint256 height = getHeight(index \u003c hashes.length ? hashes.length : (index + 1));\n        proof = new bytes32[](height);\n        uint256 levelLength = hashes.length;\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Use sibling for the merkle proof; `index^1` is index of our sibling\n                proof[h] = (index ^ 1 \u003c levelLength) ? hashes[index ^ 1] : bytes32(0);\n\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\"\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n                // Traverse to parent node\n                index \u003e\u003e= 1;\n            }\n        }\n    }\n\n    /// @notice Returns the height of the tree having a given amount of leafs.\n    function getHeight(uint256 leafs) internal pure returns (uint256 height) {\n        uint256 amount = 1;\n        while (amount \u003c leafs) {\n            unchecked {\n                ++height;\n            }\n            amount \u003c\u003c= 1;\n        }\n    }\n}\n\n// contracts/libs/stack/GasData.sol\n\n/// GasData in encoded data with \"basic information about gas prices\" for some chain.\ntype GasData is uint96;\n\nusing GasDataLib for GasData global;\n\n/// ChainGas is encoded data with given chain's \"basic information about gas prices\".\ntype ChainGas is uint128;\n\nusing GasDataLib for ChainGas global;\n\n/// Library for encoding and decoding GasData and ChainGas structs.\n/// # GasData\n/// `GasData` is a struct to store the \"basic information about gas prices\", that could\n/// be later used to approximate the cost of a message execution, and thus derive the\n/// minimal tip values for sending a message to the chain.\n/// \u003e - `GasData` is supposed to be cached by `GasOracle` contract, allowing to store the\n/// \u003e approximates instead of the exact values, and thus save on storage costs.\n/// \u003e - For instance, if `GasOracle` only updates the values on +- 10% change, having an\n/// \u003e 0.4% error on the approximates would be acceptable.\n/// `GasData` is supposed to be included in the Origin's state, which are synced across\n/// chains using Agent-signed snapshots and attestations.\n/// ## GasData stack layout (from highest bits to lowest)\n///\n/// | Position   | Field        | Type   | Bytes | Description                                         |\n/// | ---------- | ------------ | ------ | ----- | --------------------------------------------------- |\n/// | (012..010] | gasPrice     | uint16 | 2     | Gas price for the chain (in Wei per gas unit)       |\n/// | (010..008] | dataPrice    | uint16 | 2     | Calldata price (in Wei per byte of content)         |\n/// | (008..006] | execBuffer   | uint16 | 2     | Tx fee safety buffer for message execution (in Wei) |\n/// | (006..004] | amortAttCost | uint16 | 2     | Amortized cost for attestation submission (in Wei)  |\n/// | (004..002] | etherPrice   | uint16 | 2     | Chain's Ether Price / Mainnet Ether Price (in BWAD) |\n/// | (002..000] | markup       | uint16 | 2     | Markup for the message execution (in BWAD)          |\n/// \u003e See Number.sol for more details on `Number` type and BWAD (binary WAD) math.\n///\n/// ## ChainGas stack layout (from highest bits to lowest)\n///\n/// | Position   | Field   | Type   | Bytes | Description      |\n/// | ---------- | ------- | ------ | ----- | ---------------- |\n/// | (016..004] | gasData | uint96 | 12    | Chain's gas data |\n/// | (004..000] | domain  | uint32 | 4     | Chain's domain   |\nlibrary GasDataLib {\n    /// @dev Amount of bits to shift to gasPrice field\n    uint96 private constant SHIFT_GAS_PRICE = 10 * 8;\n    /// @dev Amount of bits to shift to dataPrice field\n    uint96 private constant SHIFT_DATA_PRICE = 8 * 8;\n    /// @dev Amount of bits to shift to execBuffer field\n    uint96 private constant SHIFT_EXEC_BUFFER = 6 * 8;\n    /// @dev Amount of bits to shift to amortAttCost field\n    uint96 private constant SHIFT_AMORT_ATT_COST = 4 * 8;\n    /// @dev Amount of bits to shift to etherPrice field\n    uint96 private constant SHIFT_ETHER_PRICE = 2 * 8;\n\n    /// @dev Amount of bits to shift to gasData field\n    uint128 private constant SHIFT_GAS_DATA = 4 * 8;\n\n    // ═════════════════════════════════════════════════ GAS DATA ══════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded GasData struct with the given fields.\n    /// @param gasPrice_        Gas price for the chain (in Wei per gas unit)\n    /// @param dataPrice_       Calldata price (in Wei per byte of content)\n    /// @param execBuffer_      Tx fee safety buffer for message execution (in Wei)\n    /// @param amortAttCost_    Amortized cost for attestation submission (in Wei)\n    /// @param etherPrice_      Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n    /// @param markup_          Markup for the message execution (in BWAD)\n    function encodeGasData(\n        Number gasPrice_,\n        Number dataPrice_,\n        Number execBuffer_,\n        Number amortAttCost_,\n        Number etherPrice_,\n        Number markup_\n    ) internal pure returns (GasData) {\n        // Number type wraps uint16, so could safely be casted to uint96\n        // forgefmt: disable-next-item\n        return GasData.wrap(\n            uint96(Number.unwrap(gasPrice_)) \u003c\u003c SHIFT_GAS_PRICE |\n            uint96(Number.unwrap(dataPrice_)) \u003c\u003c SHIFT_DATA_PRICE |\n            uint96(Number.unwrap(execBuffer_)) \u003c\u003c SHIFT_EXEC_BUFFER |\n            uint96(Number.unwrap(amortAttCost_)) \u003c\u003c SHIFT_AMORT_ATT_COST |\n            uint96(Number.unwrap(etherPrice_)) \u003c\u003c SHIFT_ETHER_PRICE |\n            uint96(Number.unwrap(markup_))\n        );\n    }\n\n    /// @notice Wraps padded uint256 value into GasData struct.\n    function wrapGasData(uint256 paddedGasData) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(paddedGasData));\n    }\n\n    /// @notice Returns the gas price, in Wei per gas unit.\n    function gasPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_GAS_PRICE));\n    }\n\n    /// @notice Returns the calldata price, in Wei per byte of content.\n    function dataPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_DATA_PRICE));\n    }\n\n    /// @notice Returns the tx fee safety buffer for message execution, in Wei.\n    function execBuffer(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_EXEC_BUFFER));\n    }\n\n    /// @notice Returns the amortized cost for attestation submission, in Wei.\n    function amortAttCost(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_AMORT_ATT_COST));\n    }\n\n    /// @notice Returns the ratio of Chain's Ether Price / Mainnet Ether Price, in BWAD math.\n    function etherPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_ETHER_PRICE));\n    }\n\n    /// @notice Returns the markup for the message execution, in BWAD math.\n    function markup(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data)));\n    }\n\n    // ════════════════════════════════════════════════ CHAIN DATA ═════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded ChainGas struct with the given fields.\n    /// @param gasData_ Chain's gas data\n    /// @param domain_  Chain's domain\n    function encodeChainGas(GasData gasData_, uint32 domain_) internal pure returns (ChainGas) {\n        // GasData type wraps uint96, so could safely be casted to uint128\n        return ChainGas.wrap(uint128(GasData.unwrap(gasData_)) \u003c\u003c SHIFT_GAS_DATA | uint128(domain_));\n    }\n\n    /// @notice Wraps padded uint256 value into ChainGas struct.\n    function wrapChainGas(uint256 paddedChainGas) internal pure returns (ChainGas) {\n        // Casting to uint128 will truncate the highest bits, which is the behavior we want\n        return ChainGas.wrap(uint128(paddedChainGas));\n    }\n\n    /// @notice Returns the chain's gas data.\n    function gasData(ChainGas data) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(ChainGas.unwrap(data) \u003e\u003e SHIFT_GAS_DATA));\n    }\n\n    /// @notice Returns the chain's domain.\n    function domain(ChainGas data) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(ChainGas.unwrap(data));\n    }\n\n    /// @notice Returns the hash for the list of ChainGas structs.\n    function snapGasHash(ChainGas[] memory snapGas) internal pure returns (bytes32 snapGasHash_) {\n        // Use assembly to calculate the hash of the array without copying it\n        // ChainGas takes a single word of storage, thus ChainGas[] is stored in the following way:\n        // 0x00: length of the array, in words\n        // 0x20: first ChainGas struct\n        // 0x40: second ChainGas struct\n        // And so on...\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Find the location where the array data starts, we add 0x20 to skip the length field\n            let loc := add(snapGas, 0x20)\n            // Load the length of the array (in words).\n            // Shifting left 5 bits is equivalent to multiplying by 32: this converts from words to bytes.\n            let len := shl(5, mload(snapGas))\n            // Calculate the hash of the array\n            snapGasHash_ := keccak256(loc, len)\n        }\n    }\n}\n\n// contracts/libs/stack/Header.sol\n\n/// Header is encoded data with \"general routing information\".\ntype Header is uint136;\n\nusing HeaderLib for Header global;\n\n/// Types of messages supported by Origin-Destination\n/// - Base: message sent by protocol user, contains tips\n/// - Manager: message sent between AgentManager contracts located on different chains, no tips\nenum MessageFlag {\n    Base,\n    Manager\n}\n\nusing HeaderLib for MessageFlag global;\n\n/// Library for formatting _the header part_ of _the messages used by Origin and Destination_.\n/// - Header represents general information for routing a Message for Origin and Destination.\n/// - Header occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n///\n/// # Header stack layout (from highest bits to lowest)\n///\n/// | Position   | Field            | Type   | Bytes | Description                             |\n/// | ---------- | ---------------- | ------ | ----- | --------------------------------------- |\n/// | (017..016] | flag             | uint8  | 1     | Flag specifying the type of message     |\n/// | (016..012] | origin           | uint32 | 4     | Domain where message originated         |\n/// | (012..008] | nonce            | uint32 | 4     | Message nonce on the origin domain      |\n/// | (008..004] | destination      | uint32 | 4     | Domain where message will be executed   |\n/// | (004..000] | optimisticPeriod | uint32 | 4     | Optimistic period that will be enforced |\nlibrary HeaderLib {\n    /// @dev Amount of bits to shift to flag field\n    uint136 private constant SHIFT_FLAG = 16 * 8;\n    /// @dev Amount of bits to shift to origin field\n    uint136 private constant SHIFT_ORIGIN = 12 * 8;\n    /// @dev Amount of bits to shift to nonce field\n    uint136 private constant SHIFT_NONCE = 8 * 8;\n    /// @dev Amount of bits to shift to destination field\n    uint136 private constant SHIFT_DESTINATION = 4 * 8;\n\n    /// @notice Returns an encoded header with provided fields\n    /// @param origin_              Domain of origin chain\n    /// @param nonce_               Message nonce on origin chain\n    /// @param destination_         Domain of destination chain\n    /// @param optimisticPeriod_    Optimistic period for message execution\n    function encodeHeader(\n        MessageFlag flag_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint32 destination_,\n        uint32 optimisticPeriod_\n    ) internal pure returns (Header) {\n        // All casts below are upcasts, so they are safe\n        // forgefmt: disable-next-item\n        return Header.wrap(\n            uint136(uint8(flag_)) \u003c\u003c SHIFT_FLAG |\n            uint136(origin_) \u003c\u003c SHIFT_ORIGIN |\n            uint136(nonce_) \u003c\u003c SHIFT_NONCE |\n            uint136(destination_) \u003c\u003c SHIFT_DESTINATION |\n            uint136(optimisticPeriod_)\n        );\n    }\n\n    /// @notice Checks that the header is a valid encoded header.\n    function isHeader(uint256 paddedHeader) internal pure returns (bool) {\n        // Check that flag is within range\n        return _flag(paddedHeader) \u003c= uint8(type(MessageFlag).max);\n    }\n\n    /// @notice Wraps the padded encoded request into a Header-typed value.\n    /// @dev The \"padded\" header is simply an encoded header casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded headers\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedHeader) internal pure returns (Header) {\n        // Check that flag is within range\n        if (!isHeader(paddedHeader)) revert FlagOutOfRange();\n        // Casting to uint136 will truncate the highest bits, which is the behavior we want\n        return Header.wrap(uint136(paddedHeader));\n    }\n\n    /// @notice Returns header's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Header header) internal pure returns (bytes32 hashedHeader) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store header in scratch space\n            mstore(0, header)\n            // Compute hash of header padded to 32 bytes\n            hashedHeader := keccak256(0, 32)\n        }\n    }\n\n    // ══════════════════════════════════════════════ HEADER SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns header's flag field\n    function flag(Header header) internal pure returns (MessageFlag) {\n        // We check that flag is within range when wrapping the header, so this cast is safe\n        return MessageFlag(_flag(Header.unwrap(header)));\n    }\n\n    /// @notice Returns header's origin field\n    function origin(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_ORIGIN);\n    }\n\n    /// @notice Returns header's nonce field\n    function nonce(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_NONCE);\n    }\n\n    /// @notice Returns header's destination field\n    function destination(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_DESTINATION);\n    }\n\n    /// @notice Returns header's optimistic seconds field\n    function optimisticPeriod(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns header's flag field without casting to MessageFlag\n    function _flag(uint256 paddedHeader) private pure returns (uint8) {\n        // Casting to uint8 will truncate the highest bits, which is the behavior we want\n        return uint8(paddedHeader \u003e\u003e SHIFT_FLAG);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n     * constructor.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall \u0026\u0026 _initialized \u003c 1) || (!AddressUpgradeable.isContract(address(this)) \u0026\u0026 _initialized == 1),\n            \"Initializable: contract is already initialized\"\n        );\n        _initialized = 1;\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: setting the version to 255 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing \u0026\u0026 _initialized \u003c version, \"Initializable: contract is already initialized\");\n        _initialized = version;\n        _initializing = true;\n        _;\n        _initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        require(_initializing, \"Initializable: contract is not initializing\");\n        _;\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized != type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint8) {\n        return _initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _initializing;\n    }\n}\n\n// contracts/interfaces/IAgentManager.sol\n\ninterface IAgentManager {\n    /**\n     * @notice Allows Inbox to open a Dispute between a Guard and a Notary, if they are both not in Dispute already.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Guard or Notary is already in Dispute.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Allows Inbox to slash an agent, if their fraud was proven.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Domain doesn't match the saved agent domain.\n     * @param domain    Domain where the Agent is active\n     * @param agent     Address of the Agent\n     * @param prover    Address that initially provided fraud proof\n     */\n    function slashAgent(uint32 domain, address agent, address prover) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest known root of the Agent Merkle Tree.\n     */\n    function agentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns the number of opened Disputes.\n     * @dev This includes the Disputes that have been resolved already.\n     */\n    function getDisputesAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns information about the dispute with the given index.\n     * @dev Will revert if dispute with given index hasn't been opened yet.\n     * @param index             Dispute index\n     * @return guard            Address of the Guard in the Dispute\n     * @return notary           Address of the Notary in the Dispute\n     * @return slashedAgent     Address of the Agent who was slashed when Dispute was resolved\n     * @return fraudProver      Address who provided fraud proof to resolve the Dispute\n     * @return reportPayload    Raw payload with report data that led to the Dispute\n     * @return reportSignature  Guard signature for the report payload\n     */\n    function getDispute(uint256 index)\n        external\n        view\n        returns (\n            address guard,\n            address notary,\n            address slashedAgent,\n            address fraudProver,\n            bytes memory reportPayload,\n            bytes memory reportSignature\n        );\n\n    /**\n     * @notice Returns the current Dispute status of a given agent. See Structures.sol for details.\n     * @dev Every returned value will be set to zero if agent was not slashed and is not in Dispute.\n     * `rival` and `disputePtr` will be set to zero if the agent was slashed without being in Dispute.\n     * @param agent         Agent address\n     * @return flag         Flag describing the current Dispute status for the agent: None/Pending/Slashed\n     * @return rival        Address of the rival agent in the Dispute\n     * @return fraudProver  Address who provided fraud proof to resolve the Dispute\n     * @return disputePtr   Index of the opened Dispute PLUS ONE. Zero if agent is not in Dispute.\n     */\n    function disputeStatus(address agent)\n        external\n        view\n        returns (DisputeFlag flag, address rival, address fraudProver, uint256 disputePtr);\n}\n\n// contracts/interfaces/IAgentSecured.sol\n\ninterface IAgentSecured {\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * between a Guard and a Notary has been opened.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * has been resolved due to one of the agents being slashed.\n     * \u003e `rivalIndex` will be ZERO, if the slashed agent was not in the Dispute.\n     * @param slashedIndex  Index of the slashed agent in the Agent Merkle Tree\n     * @param rivalIndex    Index of the their Dispute Rival in the Agent Merkle Tree\n     */\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the address of the local AgentManager contract, which is treated as\n     * the \"source of truth\" for agent statuses.\n     */\n    function agentManager() external view returns (address);\n\n    /**\n     * @notice Returns the address of the local Inbox contract, which is treated as\n     * the \"source of truth\" for agent-signed statements.\n     * @dev Inbox passes verified agent statements to `IAgentSecured` contract.\n     */\n    function inbox() external view returns (address);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns (flag, openedAt, resolvedAt) that describes the latest status of\n     * the latest dispute for an agent with a given index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param agentIndex    Agent index in the Agent Merkle Tree\n     * @return              Latest dispute status for the given agent: (flag, openedAt, resolvedAt)\n     */\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory);\n}\n\n// contracts/libs/memory/ByteString.sol\n\n/// @dev CallData is a memory view over the payload to be used for an external call, i.e.\n/// recipient.call(callData). Its length is always (4 + 32 * N) bytes:\n/// - First 4 bytes represent the function selector.\n/// - 32 * N bytes represent N words that function arguments occupy.\ntype CallData is uint256;\n\n/// @dev Attach library functions to CallData\nusing ByteString for CallData global;\n\n/// @dev Signature is a memory view over a \"65 bytes\" array representing a ECDSA signature.\ntype Signature is uint256;\n\n/// @dev Attach library functions to Signature\nusing ByteString for Signature global;\n\nlibrary ByteString {\n    using MemViewLib for bytes;\n\n    /**\n     * @dev non-compact ECDSA signatures are enforced as of OZ 4.7.3\n     *\n     *      Signature payload memory layout\n     * [000 .. 032) r   bytes32 32 bytes\n     * [032 .. 064) s   bytes32 32 bytes\n     * [064 .. 065) v   uint8    1 byte\n     */\n    uint256 internal constant SIGNATURE_LENGTH = 65;\n    uint256 private constant OFFSET_R = 0;\n    uint256 private constant OFFSET_S = 32;\n    uint256 private constant OFFSET_V = 64;\n\n    /**\n     * @dev Calldata memory layout\n     * [000 .. 004) selector    bytes4  4 bytes\n     *      Optional: N function arguments\n     * [004 .. 036) arg1        bytes32 32 bytes\n     *      ..\n     * [AAA .. END) argN        bytes32 32 bytes\n     */\n    uint256 internal constant SELECTOR_LENGTH = 4;\n    uint256 private constant OFFSET_SELECTOR = 0;\n    uint256 private constant OFFSET_ARGUMENTS = SELECTOR_LENGTH;\n\n    // ═════════════════════════════════════════════════ SIGNATURE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the signature payload from the given values.\n     * @dev Using ByteString.formatSignature({r: r, s: s, v: v}) will make sure\n     * that params are given in the right order.\n     */\n    function formatSignature(bytes32 r, bytes32 s, uint8 v) internal pure returns (bytes memory) {\n        return abi.encodePacked(r, s, v);\n    }\n\n    /**\n     * @notice Returns a Signature view over for the given payload.\n     * @dev Will revert if the payload is not a signature.\n     */\n    function castToSignature(bytes memory payload) internal pure returns (Signature) {\n        return castToSignature(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Signature view.\n     * @dev Will revert if the memory view is not over a signature.\n     */\n    function castToSignature(MemView memView) internal pure returns (Signature) {\n        if (!isSignature(memView)) revert UnformattedSignature();\n        return Signature.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a signature\n     */\n    function isSignature(MemView memView) internal pure returns (bool) {\n        return memView.len() == SIGNATURE_LENGTH;\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Signature signature) internal pure returns (MemView) {\n        return MemView.wrap(Signature.unwrap(signature));\n    }\n\n    // ═════════════════════════════════════════════ SIGNATURE SLICING ═════════════════════════════════════════════════\n\n    /// @notice Unpacks signature payload into (r, s, v) parameters.\n    /// @dev Make sure to verify signature length with isSignature() beforehand.\n    function toRSV(Signature signature) internal pure returns (bytes32 r, bytes32 s, uint8 v) {\n        // Get the underlying memory view\n        MemView memView = unwrap(signature);\n        r = memView.index({index_: OFFSET_R, bytes_: 32});\n        s = memView.index({index_: OFFSET_S, bytes_: 32});\n        // Can be safely casted to uint8, since we index a single byte\n        v = uint8(memView.indexUint({index_: OFFSET_V, bytes_: 1}));\n    }\n\n    // ═════════════════════════════════════════════════ CALLDATA ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the calldata with the modified arguments:\n     * the existing arguments are prepended with the arguments from the prefix.\n     * @dev Given:\n     *  - `calldata = abi.encodeWithSelector(foo.selector, d, e);`\n     *  - `prefix = abi.encode(a, b, c);`\n     *  - `a`, `b`, `c` are arguments of static type (i.e. not dynamically sized ones)\n     *      Then:\n     *  - Function will return abi.encodeWithSelector(foo.selector, a, c, c, d, e)\n     *  - Returned calldata will trigger `foo(a, b, c, d, e)` when used for a contract call.\n     * Note: for clarification as to what types are considered static, see\n     * https://docs.soliditylang.org/en/latest/abi-spec.html#formal-specification-of-the-encoding\n     * @param callData  Calldata that needs to be modified\n     * @param prefix    ABI-encoded arguments to use as the first arguments in the new calldata\n     * @return Modified calldata having prefix as the first arguments.\n     */\n    function addPrefix(CallData callData, bytes memory prefix) internal view returns (bytes memory) {\n        // Prefix should occupy a whole amount of words in memory\n        if (!_fullWords(prefix.length)) revert UnformattedCallDataPrefix();\n        MemView[] memory views = new MemView[](3);\n        // Use payload's function selector\n        views[0] = abi.encodePacked(callData.callSelector()).ref();\n        // Use prefix as the first arguments\n        views[1] = prefix.ref();\n        // Use payload's remaining arguments\n        views[2] = callData.arguments();\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a CallData view over for the given payload.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(bytes memory payload) internal pure returns (CallData) {\n        return castToCallData(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a CallData view.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(MemView memView) internal pure returns (CallData) {\n        if (!isCallData(memView)) revert UnformattedCallData();\n        return CallData.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a valid calldata, i.e.\n     * a function selector, followed by arbitrary amount of arguments.\n     */\n    function isCallData(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Calldata should at least have a function selector\n        if (length \u003c SELECTOR_LENGTH) return false;\n        // The remainder of the calldata should be exactly N memory words (N \u003e= 0)\n        return _fullWords(length - SELECTOR_LENGTH);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(CallData callData) internal pure returns (MemView) {\n        return MemView.wrap(CallData.unwrap(callData));\n    }\n\n    /// @notice Returns callData's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(CallData callData) internal pure returns (bytes32) {\n        return callData.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ CALLDATA SLICING ══════════════════════════════════════════════════\n\n    /**\n     * @notice Returns amount of memory words (32 byte chunks) the function arguments\n     * occupy in the calldata.\n     * @dev This might differ from amount of arguments supplied, if any of the arguments\n     * occupies more than one memory slot. It is true, however, that argument part of the payload\n     * occupies exactly N words, even for dynamic types like `bytes`\n     */\n    function argumentWords(CallData callData) internal pure returns (uint256) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        // Equivalent of (length - SELECTOR_LENGTH) / 32\n        return (memView.len() - SELECTOR_LENGTH) \u003e\u003e 5;\n    }\n\n    /// @notice Returns selector for the provided calldata.\n    function callSelector(CallData callData) internal pure returns (bytes4) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return bytes4(memView.index({index_: OFFSET_SELECTOR, bytes_: SELECTOR_LENGTH}));\n    }\n\n    /// @notice Returns abi encoded arguments for the provided calldata.\n    function arguments(CallData callData) internal pure returns (MemView) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return memView.sliceFrom({index_: OFFSET_ARGUMENTS});\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if length is full amount of memory words (32 bytes).\n    function _fullWords(uint256 length) internal pure returns (bool) {\n        // The equivalent of length % 32 == 0\n        return length \u0026 31 == 0;\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n    function __Context_init() internal onlyInitializing {\n    }\n\n    function __Context_init_unchained() internal onlyInitializing {\n    }\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[50] private __gap;\n}\n\n// contracts/libs/merkle/MerkleTree.sol\n\n/// `BaseTree` is a struct representing incremental merkle tree.\n/// - Contains only the current branch.\n/// - The number of inserted leaves is stored externally, and is later supplied for tree operations.\n/// - Has a fixed height of `ORIGIN_TREE_HEIGHT`.\n/// - Can store up to `2 ** ORIGIN_TREE_HEIGHT - 1` leaves.\n/// \u003e Note: the hash function for the tree `H(x, y)` is defined as:\n/// \u003e - `H(0,0) = 0`\n/// \u003e - `H(x,y) = keccak256(x, y), when (x != 0 || y != 0)`\n/// ## Invariant for leafs\n/// - The leftmost empty leaf has `index == count`, where `count` is the amount of the inserted leafs so far.\n/// - Value for any empty leaf or node is bytes32(0).\n/// ## Invariant for current branch\n/// `branch[i]` is always the value of a node on the i-th level.\n/// Levels are numbered from leafs to root: `0 .. ORIGIN_TREE_HEIGHT`.\n/// `branch[i]` stores the value for the node, such that:\n//  - The node is a \"left child\" (e.g. has an even index).\n/// - The node must have two non-empty children.\n/// - Out of all level's \"left child\" nodes with \"non-empty children\",\n/// the one with the biggest index (the rightmost one) is stored as `branch[i]`.\n/// \u003e __`branch` could be used to form a proof of inclusion for the first empty leaf (`index == count`).__\n/// _Here is how:_\n/// - Let's walk along the path from the \"first empty leaf\" to the root.\n/// - i-th bit of the \"first empty leaf\" index (which is equal to `count`) determines if the path's node\n/// for this i-th level is a \"left child\" or a \"right child\".\n/// - i-th bit in `count` is 0 → we are the left child on this level → sibling is the right child\n/// that does not exist yet → `proof[i] = bytes32(0)`.\n/// - i-th bit in `count` is 1 → we are the right child on this level → sibling is the left child\n/// sibling is the rightmost \"left child\" node on the level → `proof[i] = branch[i]`.\n/// \u003e Therefore `proof[i] = (count \u0026 (1 \u003c\u003c i)) == 0 ? bytes32(0) : branch[i])`\nstruct BaseTree {\n    bytes32[ORIGIN_TREE_HEIGHT] branch;\n}\n\nusing MerkleTree for BaseTree global;\n\n/// `HistoricalTree` is an incremental merkle tree keeping track of its historical merkle roots.\n/// \u003e - `roots[N]` is the root of the tree after `N` leafs were inserted\n/// \u003e - `roots[0] == bytes32(0)`\n/// @param tree     Incremental merkle tree\n/// @param roots    Historical merkle roots of the tree\nstruct HistoricalTree {\n    BaseTree tree;\n    bytes32[] roots;\n}\n\nusing MerkleTree for HistoricalTree global;\n\n/// `DynamicTree` is a struct representing a Merkle Tree with `2**AGENT_TREE_HEIGHT` leaves.\n/// - A single operation is available: update value for leaf with an arbitrary index (which might be a non-empty leaf).\n/// - This is done by requesting the proof of inclusion for the old value, which is used to both\n/// verify the old value, and calculate the new root.\n/// \u003e Based on Original idea from [ER forum post](https://ethresear.ch/t/efficient-on-chain-dynamic-merkle-tree/11054).\nstruct DynamicTree {\n    bytes32 root;\n}\n\nusing MerkleTree for DynamicTree global;\n\n/// MerkleTree is work based on Nomad's Merkle.sol, which is used under MIT OR Apache-2.0\n/// [link](https://github.com/nomad-xyz/monorepo/blob/main/packages/contracts-core/contracts/libs/Merkle.sol).\n/// With the following changes:\n/// - Adapted for Solidity 0.8.x.\n/// - Amount of tree leaves stored externally.\n/// - Added thorough documentation.\n/// - `H(0,0) = 0` optimization from [ER forum post](https://ethresear.ch/t/optimizing-sparse-merkle-trees/3751/6).\n/// \u003e Nomad's Merkle.sol is work based on eth2 deposit contract, which is used under CC0-1.0\n///[link](https://github.com/ethereum/deposit_contract/blob/dev/deposit_contract/contracts/validator_registration.v.py).\n/// With the following changes:\n/// \u003e - Implemented in Solidity 0.7.6 (eth2 deposit contract implemented in Vyper).\n/// \u003e - `H() = keccak256()` is used as the hashing function instead of `sha256()`.\nlibrary MerkleTree {\n    /// @dev For root calculation we need at least one empty leaf, thus the minus one in the formula.\n    uint256 internal constant MAX_LEAVES = 2 ** ORIGIN_TREE_HEIGHT - 1;\n\n    // ═════════════════════════════════════════════════ BASE TREE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Inserts `node` into merkle tree\n     * @dev Reverts if tree is full\n     * @param newCount  Amount of inserted leaves in the tree after the insertion (i.e. current + 1)\n     * @param node      Element to insert into tree\n     */\n    function insertBase(BaseTree storage tree, uint256 newCount, bytes32 node) internal {\n        if (newCount \u003e MAX_LEAVES) revert MerkleTreeFull();\n        // We go up the tree following the branch from the empty leaf AFTER the just inserted one.\n        // We stop when we find the first \"right child\" node.\n        // Its sibling is now the rightmost \"left child\" node that has two non-empty children.\n        // Therefore we need to update `tree.branch` value on this level.\n        // One could see that `tree.branch` value on lower and higher levels remain unchanged.\n\n        // Loop invariant: `node` is the current level's value for the branch from JUST INSERTED leaf\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            if ((newCount \u0026 1) == 1) {\n                // Found the first \"right child\" node on the branch from EMPTY leaf\n                // `node` is the value for node on branch from JUST INSERTED leaf\n                // Which in this case is the \"left child\".\n                // We update tree.branch and exit\n                tree.branch[i] = node;\n                return;\n            }\n            // On the branch from EMPTY leaf this is still a \"left child\".\n            // Meaning on branch from JUST INSERTED leaf, `node` is a right child.\n            // We compute value for `node` parent using `tree.branch` invariant:\n            // This is the rightmost \"left child\" node, which would be sibling of `node`.\n            node = MerkleMath.getParent(tree.branch[i], node);\n            // Get the parent index, and go to the next tree level\n            newCount \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n        // As the loop should always end prematurely with the `return` statement,\n        // this code should be unreachable. We assert `false` just to be safe.\n        assert(false);\n    }\n\n    /**\n     * @notice Calculates and returns current root of the merkle tree.\n     * @param count     Current amount of inserted leaves in the tree\n     * @return current  Calculated root of `tree`\n     */\n    function rootBase(BaseTree storage tree, uint256 count) internal view returns (bytes32 current) {\n        // To calculate the root we follow the branch of first EMPTY leaf (index == count)\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            // Check if we are the left or the right child on the current level\n            if ((count \u0026 1) == 1) {\n                // We are the right child. Our sibling is the \"rightmost\" \"left-child\" node\n                // that has two non-empty children → sibling is `tree.branch[i]`\n                current = MerkleMath.getParent(tree.branch[i], current);\n            } else {\n                // We are the left child. Our sibling does not exist yet → sibling is EMPTY\n                current = MerkleMath.getParent(current, bytes32(0));\n            }\n            // Get the parent index, and go to the next tree level\n            count \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    // ══════════════════════════════════════════════ HISTORICAL TREE ══════════════════════════════════════════════════\n\n    /// @notice Initializes the historical roots for the tree by inserting an empty root.\n    // solhint-disable-next-line ordering\n    function initializeRoots(HistoricalTree storage tree) internal returns (bytes32 savedRoot) {\n        // This should only be called once, when the contract is initialized\n        assert(tree.roots.length == 0);\n        // Save root for empty merkle tree: bytes32(0)\n        tree.roots.push(savedRoot);\n    }\n\n    /// @notice Inserts a new leaf into the merkle tree.\n    /// @dev Reverts if tree is full.\n    /// @param node         Element to insert into tree\n    /// @return newRoot     Merkle root after the leaf was inserted\n    function insert(HistoricalTree storage tree, bytes32 node) internal returns (bytes32 newRoot) {\n        // Tree count after the new leaf will be inserted (we store roots[0] as root of empty tree)\n        uint256 newCount = tree.roots.length;\n        tree.tree.insertBase(newCount, node);\n        // Save the new root\n        newRoot = tree.tree.rootBase(newCount);\n        tree.roots.push(newRoot);\n    }\n\n    /// @notice Returns the historical root of the merkle tree.\n    /// @dev Reverts if not enough leafs have been inserted.\n    /// @param count            Amount of leafs in the tree at some point of time\n    /// @return historicalRoot  Merkle root after `count` leafs were inserted\n    function root(HistoricalTree storage tree, uint256 count) internal view returns (bytes32 historicalRoot) {\n        if (count \u003e= tree.roots.length) revert NotEnoughLeafs();\n        return tree.roots[count];\n    }\n\n    // ═══════════════════════════════════════════════ DYNAMIC TREE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Updates the value for the leaf with the given index in the Dynamic Merkle Tree.\n     * @dev Will revert if incorrect proof of inclusion for old value is supplied.\n     * @param tree          Dynamic merkle tree\n     * @param index         Index of the leaf to update\n     * @param oldValue      Previous value of the leaf\n     * @param branch        Proof of inclusion of previous value into the tree\n     * @param newValue      New leaf value to assign\n     * @return newRoot      New value for the Merkle Root after the leaf is updated\n     */\n    function update(\n        DynamicTree storage tree,\n        uint256 index,\n        bytes32 oldValue,\n        bytes32[] memory branch,\n        bytes32 newValue\n    ) internal returns (bytes32 newRoot) {\n        // Check that the old value + proof result in a correct root\n        if (MerkleMath.proofRoot(index, oldValue, branch, AGENT_TREE_HEIGHT) != tree.root) {\n            revert LeafNotProven();\n        }\n        // New root is new value + the same proof (values for sibling nodes are not updated)\n        newRoot = MerkleMath.proofRoot(index, newValue, branch, AGENT_TREE_HEIGHT);\n        // Write the new root\n        tree.root = newRoot;\n    }\n}\n\n// contracts/libs/stack/Tips.sol\n\n/// Tips is encoded data with \"tips paid for sending a base message\".\n/// Note: even though uint256 is also an underlying type for MemView, Tips is stored ON STACK.\ntype Tips is uint256;\n\nusing TipsLib for Tips global;\n\n/// # Tips\n/// Library for formatting _the tips part_ of _the base messages_.\n///\n/// ## How the tips are awarded\n/// Tips are paid for sending a base message, and are split across all the agents that\n/// made the message execution on destination chain possible.\n/// ### Summit tips\n/// Split between:\n///     - Guard posting a snapshot with state ST_G for the origin chain.\n///     - Notary posting a snapshot SN_N using ST_G. This creates attestation A.\n///     - Notary posting a message receipt after it is executed on destination chain.\n/// ### Attestation tips\n/// Paid to:\n///     - Notary posting attestation A to destination chain.\n/// ### Execution tips\n/// Paid to:\n///     - First executor performing a valid execution attempt (correct proofs, optimistic period over),\n///      using attestation A to prove message inclusion on origin chain, whether the recipient reverted or not.\n/// ### Delivery tips.\n/// Paid to:\n///     - Executor who successfully executed the message on destination chain.\n///\n/// ## Tips encoding\n/// - Tips occupy a single storage word, and thus are stored on stack instead of being stored in memory.\n/// - The actual tip values should be determined by multiplying stored values by divided by TIPS_MULTIPLIER=2**32.\n/// - Tips are packed into a single word of storage, while allowing real values up to ~8*10**28 for every tip category.\n/// \u003e The only downside is that the \"real tip values\" are now multiplies of ~4*10**9, which should be fine even for\n/// the chains with the most expensive gas currency.\n/// # Tips stack layout (from highest bits to lowest)\n///\n/// | Position   | Field          | Type   | Bytes | Description                                                |\n/// | ---------- | -------------- | ------ | ----- | ---------------------------------------------------------- |\n/// | (032..024] | summitTip      | uint64 | 8     | Tip for agents interacting with Summit contract            |\n/// | (024..016] | attestationTip | uint64 | 8     | Tip for Notary posting attestation to Destination contract |\n/// | (016..008] | executionTip   | uint64 | 8     | Tip for valid execution attempt on destination chain       |\n/// | (008..000] | deliveryTip    | uint64 | 8     | Tip for successful message delivery on destination chain   |\n\nlibrary TipsLib {\n    using SafeCast for uint256;\n\n    /// @dev Amount of bits to shift to summitTip field\n    uint256 private constant SHIFT_SUMMIT_TIP = 24 * 8;\n    /// @dev Amount of bits to shift to attestationTip field\n    uint256 private constant SHIFT_ATTESTATION_TIP = 16 * 8;\n    /// @dev Amount of bits to shift to executionTip field\n    uint256 private constant SHIFT_EXECUTION_TIP = 8 * 8;\n\n    // ═══════════════════════════════════════════════════ TIPS ════════════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips with the given fields\n    /// @param summitTip_        Tip for agents interacting with Summit contract, divided by TIPS_MULTIPLIER\n    /// @param attestationTip_   Tip for Notary posting attestation to Destination contract, divided by TIPS_MULTIPLIER\n    /// @param executionTip_     Tip for valid execution attempt on destination chain, divided by TIPS_MULTIPLIER\n    /// @param deliveryTip_      Tip for successful message delivery on destination chain, divided by TIPS_MULTIPLIER\n    function encodeTips(uint64 summitTip_, uint64 attestationTip_, uint64 executionTip_, uint64 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // forgefmt: disable-next-item\n        return Tips.wrap(\n            uint256(summitTip_) \u003c\u003c SHIFT_SUMMIT_TIP |\n            uint256(attestationTip_) \u003c\u003c SHIFT_ATTESTATION_TIP |\n            uint256(executionTip_) \u003c\u003c SHIFT_EXECUTION_TIP |\n            uint256(deliveryTip_)\n        );\n    }\n\n    /// @notice Convenience function to encode tips with uint256 values.\n    function encodeTips256(uint256 summitTip_, uint256 attestationTip_, uint256 executionTip_, uint256 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // In practice, the tips amounts are not supposed to be higher than 2**96, and with 32 bits of granularity\n        // using uint64 is enough to store the values. However, we still check for overflow just in case.\n        // TODO: consider using Number type to store the tips values.\n        return encodeTips({\n            summitTip_: (summitTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            attestationTip_: (attestationTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            executionTip_: (executionTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            deliveryTip_: (deliveryTip_ \u003e\u003e TIPS_GRANULARITY).toUint64()\n        });\n    }\n\n    /// @notice Wraps the padded encoded tips into a Tips-typed value.\n    /// @dev There is no actual padding here, as the underlying type is already uint256,\n    /// but we include this function for consistency and to be future-proof, if tips will eventually use anything\n    /// smaller than uint256.\n    function wrapPadded(uint256 paddedTips) internal pure returns (Tips) {\n        return Tips.wrap(paddedTips);\n    }\n\n    /**\n     * @notice Returns a formatted Tips payload specifying empty tips.\n     * @return Formatted tips\n     */\n    function emptyTips() internal pure returns (Tips) {\n        return Tips.wrap(0);\n    }\n\n    /// @notice Returns tips's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Tips tips) internal pure returns (bytes32 hashedTips) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store tips in scratch space\n            mstore(0, tips)\n            // Compute hash of tips padded to 32 bytes\n            hashedTips := keccak256(0, 32)\n        }\n    }\n\n    // ═══════════════════════════════════════════════ TIPS SLICING ════════════════════════════════════════════════════\n\n    /// @notice Returns summitTip field\n    function summitTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_SUMMIT_TIP);\n    }\n\n    /// @notice Returns attestationTip field\n    function attestationTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_ATTESTATION_TIP);\n    }\n\n    /// @notice Returns executionTip field\n    function executionTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_EXECUTION_TIP);\n    }\n\n    /// @notice Returns deliveryTip field\n    function deliveryTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips));\n    }\n\n    // ════════════════════════════════════════════════ TIPS VALUE ═════════════════════════════════════════════════════\n\n    /// @notice Returns total value of the tips payload.\n    /// This is the sum of the encoded values, scaled up by TIPS_MULTIPLIER\n    function value(Tips tips) internal pure returns (uint256 value_) {\n        value_ = uint256(tips.summitTip()) + tips.attestationTip() + tips.executionTip() + tips.deliveryTip();\n        value_ \u003c\u003c= TIPS_GRANULARITY;\n    }\n\n    /// @notice Increases the delivery tip to match the new value.\n    function matchValue(Tips tips, uint256 newValue) internal pure returns (Tips newTips) {\n        uint256 oldValue = tips.value();\n        if (newValue \u003c oldValue) revert TipsValueTooLow();\n        // We want to increase the delivery tip, while keeping the other tips the same\n        unchecked {\n            uint256 delta = (newValue - oldValue) \u003e\u003e TIPS_GRANULARITY;\n            // `delta` fits into uint224, as TIPS_GRANULARITY is 32, so this never overflows uint256.\n            // In practice, this will never overflow uint64 as well, but we still check it just in case.\n            if (delta + tips.deliveryTip() \u003e type(uint64).max) revert TipsOverflow();\n            // Delivery tips occupy lowest 8 bytes, so we can just add delta to the tips value\n            // to effectively increase the delivery tip (knowing that delta fits into uint64).\n            newTips = Tips.wrap(Tips.unwrap(tips) + delta);\n        }\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    function __Ownable_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable_init_unchained() internal onlyInitializing {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n    function __Ownable2Step_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable2Step_init_unchained() internal onlyInitializing {\n    }\n    address private _pendingOwner;\n\n    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Returns the address of the pending owner.\n     */\n    function pendingOwner() public view virtual returns (address) {\n        return _pendingOwner;\n    }\n\n    /**\n     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual override onlyOwner {\n        _pendingOwner = newOwner;\n        emit OwnershipTransferStarted(owner(), newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual override {\n        delete _pendingOwner;\n        super._transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev The new owner accepts the ownership transfer.\n     */\n    function acceptOwnership() public virtual {\n        address sender = _msgSender();\n        require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n        _transferOwnership(sender);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// contracts/libs/memory/State.sol\n\n/// State is a memory view over a formatted state payload.\ntype State is uint256;\n\nusing StateLib for State global;\n\n/// # State\n/// State structure represents the state of Origin contract at some point of time.\n/// - State is structured in a way to track the updates of the Origin Merkle Tree.\n/// - State includes root of the Origin Merkle Tree, origin domain and some additional metadata.\n/// ## Origin Merkle Tree\n/// Hash of every sent message is inserted in the Origin Merkle Tree, which changes\n/// the value of Origin Merkle Root (which is the root for the mentioned tree).\n/// - Origin has a single Merkle Tree for all messages, regardless of their destination domain.\n/// - This leads to Origin state being updated if and only if a message was sent in a block.\n/// - Origin contract is a \"source of truth\" for states: a state is considered \"valid\" in its Origin,\n/// if it matches the state of the Origin contract after the N-th (nonce) message was sent.\n///\n/// # Memory layout of State fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                    |\n/// | ---------- | ----------- | ------- | ----- | ------------------------------ |\n/// | [000..032) | root        | bytes32 | 32    | Root of the Origin Merkle Tree |\n/// | [032..036) | origin      | uint32  | 4     | Domain where Origin is located |\n/// | [036..040) | nonce       | uint32  | 4     | Amount of sent messages        |\n/// | [040..045) | blockNumber | uint40  | 5     | Block of last sent message     |\n/// | [045..050) | timestamp   | uint40  | 5     | Time of last sent message      |\n/// | [050..062) | gasData     | uint96  | 12    | Gas data for the chain         |\n///\n/// @dev State could be used to form a Snapshot to be signed by a Guard or a Notary.\nlibrary StateLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_ROOT = 0;\n    uint256 private constant OFFSET_ORIGIN = 32;\n    uint256 private constant OFFSET_NONCE = 36;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 40;\n    uint256 private constant OFFSET_TIMESTAMP = 45;\n    uint256 private constant OFFSET_GAS_DATA = 50;\n\n    // ═══════════════════════════════════════════════════ STATE ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted State payload with provided fields\n     * @param root_         New merkle root\n     * @param origin_       Domain of Origin's chain\n     * @param nonce_        Nonce of the merkle root\n     * @param blockNumber_  Block number when root was saved in Origin\n     * @param timestamp_    Block timestamp when root was saved in Origin\n     * @param gasData_      Gas data for the chain\n     * @return Formatted state\n     */\n    function formatState(\n        bytes32 root_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_,\n        GasData gasData_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(root_, origin_, nonce_, blockNumber_, timestamp_, gasData_);\n    }\n\n    /**\n     * @notice Returns a State view over the given payload.\n     * @dev Will revert if the payload is not a state.\n     */\n    function castToState(bytes memory payload) internal pure returns (State) {\n        return castToState(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a State view.\n     * @dev Will revert if the memory view is not over a state.\n     */\n    function castToState(MemView memView) internal pure returns (State) {\n        if (!isState(memView)) revert UnformattedState();\n        return State.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted State.\n    function isState(MemView memView) internal pure returns (bool) {\n        return memView.len() == STATE_LENGTH;\n    }\n\n    /// @notice Returns the hash of a State, that could be later signed by a Guard to signal\n    /// that the state is invalid.\n    function hashInvalid(State state) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(stateInvalidSalt, keccak(state))\n        return state.unwrap().keccakSalted(STATE_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(State state) internal pure returns (MemView) {\n        return MemView.wrap(State.unwrap(state));\n    }\n\n    /// @notice Compares two State structures.\n    function equals(State a, State b) internal pure returns (bool) {\n        // Length of a State payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═══════════════════════════════════════════════ STATE HASHING ═══════════════════════════════════════════════════\n\n    /// @notice Returns the hash of the State.\n    /// @dev We are using the Merkle Root of a tree with two leafs (see below) as state hash.\n    function leaf(State state) internal pure returns (bytes32) {\n        (bytes32 leftLeaf_, bytes32 rightLeaf_) = state.subLeafs();\n        // Final hash is the parent of these leafs\n        return keccak256(bytes.concat(leftLeaf_, rightLeaf_));\n    }\n\n    /// @notice Returns \"sub-leafs\" of the State. Hash of these \"sub leafs\" is going to be used\n    /// as a \"state leaf\" in the \"Snapshot Merkle Tree\".\n    /// This enables proving that leftLeaf = (root, origin) was a part of the \"Snapshot Merkle Tree\",\n    /// by combining `rightLeaf` with the remainder of the \"Snapshot Merkle Proof\".\n    function subLeafs(State state) internal pure returns (bytes32 leftLeaf_, bytes32 rightLeaf_) {\n        MemView memView = state.unwrap();\n        // Left leaf is (root, origin)\n        leftLeaf_ = memView.prefix({len_: OFFSET_NONCE}).keccak();\n        // Right leaf is (metadata), or (nonce, blockNumber, timestamp)\n        rightLeaf_ = memView.sliceFrom({index_: OFFSET_NONCE}).keccak();\n    }\n\n    /// @notice Returns the left \"sub-leaf\" of the State.\n    function leftLeaf(bytes32 root_, uint32 origin_) internal pure returns (bytes32) {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(root_, origin_));\n    }\n\n    /// @notice Returns the right \"sub-leaf\" of the State.\n    function rightLeaf(uint32 nonce_, uint40 blockNumber_, uint40 timestamp_, GasData gasData_)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(nonce_, blockNumber_, timestamp_, gasData_));\n    }\n\n    // ═══════════════════════════════════════════════ STATE SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns a historical Merkle root from the Origin contract.\n    function root(State state) internal pure returns (bytes32) {\n        return state.unwrap().index({index_: OFFSET_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns domain of chain where the Origin contract is deployed.\n    function origin(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns nonce of Origin contract at the time, when `root` was the Merkle root.\n    function nonce(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when `root` was saved in Origin.\n    function blockNumber(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when `root` was saved in Origin.\n    /// @dev This is the timestamp according to the origin chain.\n    function timestamp(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n\n    /// @notice Returns gas data for the chain.\n    function gasData(State state) internal pure returns (GasData) {\n        return GasDataLib.wrapGasData(state.unwrap().indexUint({index_: OFFSET_GAS_DATA, bytes_: GAS_DATA_LENGTH}));\n    }\n}\n\n// contracts/libs/memory/BaseMessage.sol\n\n/// BaseMessage is a memory view over the base message supported by Origin-Destination\ntype BaseMessage is uint256;\n\nusing BaseMessageLib for BaseMessage global;\n\n/// BaseMessage structure represents a base message sent via the Origin-Destination contracts.\n/// - It only contains data relevant to the base message, the rest of data is encoded in the message header.\n/// - `sender` and `recipient` for EVM chains are EVM addresses casted to bytes32, while preserving left-alignment.\n/// - `tips` and `request` parameters are specified by a message sender\n/// \u003e Origin will calculate minimum tips for given request and content length, and will reject messages with tips\n/// lower than that.\n///\n/// # Memory layout of BaseMessage fields\n///\n/// | Position   | Field     | Type    | Bytes | Description                            |\n/// | ---------- | --------- | ------- | ----- | -------------------------------------- |\n/// | [000..032) | tips      | uint256 | 32    | Encoded tips paid on origin chain      |\n/// | [032..064) | sender    | bytes32 | 32    | Sender address on origin chain         |\n/// | [064..096) | recipient | bytes32 | 32    | Recipient address on destination chain |\n/// | [096..116) | request   | uint160 | 20    | Encoded request for message execution  |\n/// | [104..AAA) | content   | bytes   | ??    | Content to be passed to recipient      |\nlibrary BaseMessageLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_TIPS = 0;\n    uint256 private constant OFFSET_SENDER = 32;\n    uint256 private constant OFFSET_RECIPIENT = 64;\n    uint256 private constant OFFSET_REQUEST = OFFSET_RECIPIENT + TIPS_LENGTH;\n    uint256 private constant OFFSET_CONTENT = OFFSET_REQUEST + REQUEST_LENGTH;\n\n    // ═══════════════════════════════════════════════ BASE MESSAGE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted BaseMessage payload with provided fields.\n     * @param tips_         Encoded tips information\n     * @param sender_       Sender address on origin chain\n     * @param recipient_    Recipient address on destination chain\n     * @param request_      Encoded request for message execution\n     * @param content_      Raw content to be passed to recipient on destination chain\n     * @return Formatted base message\n     */\n    function formatBaseMessage(Tips tips_, bytes32 sender_, bytes32 recipient_, Request request_, bytes memory content_)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return abi.encodePacked(tips_, sender_, recipient_, request_, content_);\n    }\n\n    /**\n     * @notice Returns a BaseMessage view over the given payload.\n     * @dev Will revert if the payload is not a base message.\n     */\n    function castToBaseMessage(bytes memory payload) internal pure returns (BaseMessage) {\n        return castToBaseMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a BaseMessage view.\n     * @dev Will revert if the memory view is not over a base message payload.\n     */\n    function castToBaseMessage(MemView memView) internal pure returns (BaseMessage) {\n        if (!isBaseMessage(memView)) revert UnformattedBaseMessage();\n        return BaseMessage.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted BaseMessage.\n    function isBaseMessage(MemView memView) internal pure returns (bool) {\n        // Check if sender, recipient, tips fields exist\n        return (memView.len() \u003e= OFFSET_CONTENT);\n        // Content could be empty, so we don't check that\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(BaseMessage baseMessage) internal pure returns (MemView) {\n        return MemView.wrap(BaseMessage.unwrap(baseMessage));\n    }\n\n    /// @notice Returns baseMessage's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        // We hash \"tips\" and \"everything but tips\" to make tips proofs easier to verify\n        return MerkleMath.getParent(baseMessage.tips().leaf(), baseMessage.bodyLeaf());\n    }\n\n    /// @notice Returns hash for the \"everything but tips\" part of the base message.\n    function bodyLeaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_SENDER}).keccak();\n    }\n\n    // ═══════════════════════════════════════════ BASE MESSAGE SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips paid on origin chain.\n    function tips(BaseMessage baseMessage) internal pure returns (Tips) {\n        return TipsLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_TIPS, bytes_: TIPS_LENGTH})));\n    }\n\n    /// @notice Returns sender address on origin chain.\n    function sender(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_SENDER, bytes_: 32});\n    }\n\n    /// @notice Returns recipient address on destination chain.\n    function recipient(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_RECIPIENT, bytes_: 32});\n    }\n\n    /// @notice Returns an encoded request for message execution on destination chain.\n    function request(BaseMessage baseMessage) internal pure returns (Request) {\n        return RequestLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_REQUEST, bytes_: REQUEST_LENGTH})));\n    }\n\n    /// @notice Returns an untyped memory view over the content to be passed to recipient.\n    function content(BaseMessage baseMessage) internal pure returns (MemView) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_CONTENT});\n    }\n}\n\n// contracts/base/MessagingBase.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for all messaging contracts.\n * - Provides context on the local chain's domain.\n * - Provides ownership functionality.\n * - Will be providing pausing functionality when it is implemented.\n */\nabstract contract MessagingBase is MultiCallable, Versioned, Ownable2StepUpgradeable {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @notice Domain of the local chain, set once upon contract creation\n    uint32 public immutable localDomain;\n    // @notice Domain of the Synapse chain, set once upon contract creation\n    uint32 public immutable synapseDomain;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev gap for upgrade safety\n    uint256[50] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    constructor(string memory version_, uint32 synapseDomain_) Versioned(version_) {\n        localDomain = ChainContext.chainId();\n        synapseDomain = synapseDomain_;\n    }\n\n    // TODO: Implement pausing\n\n    /**\n     * @dev Should be impossible to renounce ownership;\n     * we override OpenZeppelin OwnableUpgradeable's\n     * implementation of renounceOwnership to make it a no-op\n     */\n    function renounceOwnership() public override onlyOwner {} //solhint-disable-line no-empty-blocks\n}\n\n// contracts/libs/memory/Message.sol\n\n/// Message is a memory over over a formatted message payload.\ntype Message is uint256;\n\nusing MessageLib for Message global;\n\n/// Library for formatting the various messages supported by Origin and Destination.\n///\n/// # Message memory layout\n///\n/// | Position   | Field  | Type    | Bytes | Description                                             |\n/// | ---------- | ------ | ------- | ----- | ------------------------------------------------------- |\n/// | [000..017) | header | uint136 | 17    | Encoded general routing information for the message     |\n/// | [017..AAA) | body   | bytes   | ??    | Formatted payload (according to flag) with message body |\nlibrary MessageLib {\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MemViewLib for bytes;\n    using HeaderLib for MemView;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_HEADER = 0;\n    uint256 private constant OFFSET_BODY = OFFSET_HEADER + HEADER_LENGTH;\n\n    // ══════════════════════════════════════════════════ MESSAGE ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns formatted message with provided fields.\n     * @param header_   Encoded general routing information for the message\n     * @param body_     Formatted payload (according to flag) with message body\n     * @return Formatted message\n     */\n    function formatMessage(Header header_, bytes memory body_) internal pure returns (bytes memory) {\n        return abi.encodePacked(header_, body_);\n    }\n\n    /**\n     * @notice Returns a Message view over for the given payload.\n     * @dev Will revert if the payload is not a message payload.\n     */\n    function castToMessage(bytes memory payload) internal pure returns (Message) {\n        return castToMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Message view.\n     * @dev Will revert if the memory view is not over a message payload.\n     */\n    function castToMessage(MemView memView) internal pure returns (Message) {\n        if (!isMessage(memView)) revert UnformattedMessage();\n        return Message.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Message.\n     */\n    function isMessage(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Check if headers exist in the payload\n        if (length \u003c OFFSET_BODY) return false;\n        // Check that Header is valid\n        uint256 paddedHeader = _header(memView);\n        if (!HeaderLib.isHeader(paddedHeader)) return false;\n        // Check that body is formatted according to the flag\n        // Only Base/Manager message flags exist\n        if (HeaderLib.wrapPadded(paddedHeader).flag() == MessageFlag.Base) {\n            // Check if body is a formatted base message\n            return _body(memView).isBaseMessage();\n        } else {\n            // Check if body is a formatted calldata for AgentManager call\n            return _body(memView).isCallData();\n        }\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Message message) internal pure returns (MemView) {\n        return MemView.wrap(Message.unwrap(message));\n    }\n\n    /// @notice Returns message's hash: a leaf to be inserted in the Merkle tree.\n    function leaf(Message message) internal pure returns (bytes32) {\n        // We hash header and body separately to make message proofs easier to verify\n        Header header_ = message.header();\n        // Only Base/Manager message flags exist\n        if (header_.flag() == MessageFlag.Base) {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToBaseMessage().leaf());\n        } else {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToCallData().leaf());\n        }\n    }\n\n    // ══════════════════════════════════════════════ MESSAGE SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns message's encoded header field.\n    function header(Message message) internal pure returns (Header) {\n        return HeaderLib.wrapPadded((message.unwrap().indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH})));\n    }\n\n    /// @notice Returns message's body field as an untyped memory view.\n    function body(Message message) internal pure returns (MemView) {\n        MemView memView = message.unwrap();\n        return _body(memView);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns message's padded header without checking that it is a valid header.\n    function _header(MemView memView) private pure returns (uint256) {\n        return memView.indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH});\n    }\n\n    /// @dev Returns an untyped memory view over the body field without checking\n    /// if the whole payload or the body are properly formatted.\n    function _body(MemView memView) private pure returns (MemView) {\n        return memView.sliceFrom({index_: OFFSET_BODY});\n    }\n}\n\n// contracts/base/AgentSecured.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for messaging contracts that are secured by the agent manager.\n * `AgentSecured` relies on `AgentManager` to provide the following functionality:\n * - Keep track of agents and their statuses.\n * - Pass agent-signed statements that were verified by the agent manager.\n * - These statements are considered valid indefinitely, unless the agent is disputed.\n * - Disputes are opened and resolved by the agent manager.\n * \u003e `AgentSecured` implementation should never use statements signed by agents that are disputed.\n */\nabstract contract AgentSecured is MessagingBase, IAgentSecured {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    address public immutable agentManager;\n\n    /// @inheritdoc IAgentSecured\n    address public immutable inbox;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    // (agent index =\u003e their dispute status: flag, openedAt, resolvedAt)\n    mapping(uint32 =\u003e DisputeStatus) internal _disputes;\n\n    /// @dev gap for upgrade safety\n    uint256[49] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    modifier onlyAgentManager() {\n        if (msg.sender != agentManager) revert CallerNotAgentManager();\n        _;\n    }\n\n    modifier onlyInbox() {\n        if (msg.sender != inbox) revert CallerNotInbox();\n        _;\n    }\n\n    constructor(string memory version_, uint32 synapseDomain_, address agentManager_, address inbox_)\n        MessagingBase(version_, synapseDomain_)\n    {\n        agentManager = agentManager_;\n        inbox = inbox_;\n    }\n\n    // ════════════════════════════════════════════ ONLY AGENT MANAGER ═════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external onlyAgentManager {\n        uint40 openedAt = ChainContext.blockTimestamp();\n        DisputeStatus memory status = DisputeStatus({flag: DisputeFlag.Pending, openedAt: openedAt, resolvedAt: 0});\n        _disputes[guardIndex] = status;\n        _disputes[notaryIndex] = status;\n    }\n\n    /// @inheritdoc IAgentSecured\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external onlyAgentManager {\n        // Update the dispute status of the slashed agent first.\n        uint40 resolvedAt = ChainContext.blockTimestamp();\n        _disputes[slashedIndex].flag = DisputeFlag.Slashed;\n        _disputes[slashedIndex].resolvedAt = resolvedAt;\n        // Mark the rival agent as not disputed, if there was an ongoing dispute.\n        if (rivalIndex != 0) {\n            _disputes[rivalIndex].flag = DisputeFlag.None;\n            _disputes[rivalIndex].resolvedAt = resolvedAt;\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function agentStatus(address agent) external view returns (AgentStatus memory) {\n        return _agentStatus(agent);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status) {\n        return _getAgent(index);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory) {\n        return _disputes[agentIndex];\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns status of the given agent: (flag, domain, index).\n    function _agentStatus(address agent) internal view returns (AgentStatus memory) {\n        return IAgentManager(agentManager).agentStatus(agent);\n    }\n\n    /// @dev Returns agent and their status for a given agent index. Returns zero values for non existing indexes.\n    function _getAgent(uint256 index) internal view returns (address agent, AgentStatus memory status) {\n        return IAgentManager(agentManager).getAgent(index);\n    }\n\n    /// @dev Checks if a Dispute exists for the given Notary. This function returns true, if\n    /// Notary is in ongoing Dispute, or if Dispute was resolved not in Notary's favor.\n    /// In both cases we can't trust Notary's data.\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeExists(uint32 notaryIndex) internal view returns (bool) {\n        return _disputes[notaryIndex].flag != DisputeFlag.None;\n    }\n\n    /// @dev Checks if a Notary recently won a Dispute and is still in the \"post-dispute\" timeout period.\n    /// In this period we still can't trust Notary's data, though we can optimistically assume that\n    /// that the data will be correct after the timeout (assuming no new Disputes are opened).\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeTimeout(uint32 notaryIndex) internal view returns (bool) {\n        DisputeStatus memory status = _disputes[notaryIndex];\n        // Exit early if Notary is in ongoing Dispute / slashed.\n        if (status.flag != DisputeFlag.None) return false;\n        // Check if Notary has been in any Dispute at all.\n        if (status.openedAt == 0) return false;\n        // Otherwise check if the Dispute timeout is still active.\n        return block.timestamp \u003c status.resolvedAt + DISPUTE_TIMEOUT_NOTARY;\n    }\n}\n\n// contracts/hubs/StateHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StateHub` is a parent contract for `Origin`. It is responsible for the following:\n/// - Keeping track of the historical Origin Merkle Tree containing all the message hashes.\n/// - Keeping track of the historical Origin States, as well as verifying their validity.\nabstract contract StateHub is AgentSecured, StateHubEvents, IStateHub {\n    using SafeCast for uint256;\n    using StateLib for bytes;\n\n    struct OriginState {\n        uint40 blockNumber;\n        uint40 timestamp;\n        GasData gasData;\n    }\n    // Bits left for tight packing: 80\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Historical Merkle Tree\n    /// Note: Takes two storage slots\n    HistoricalTree private _tree;\n\n    /// @dev All historical contract States\n    OriginState[] private _originStates;\n\n    /// @dev gap for upgrade safety\n    uint256[47] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IStateHub\n    function isValidState(bytes memory statePayload) external view returns (bool isValid) {\n        // This will revert if payload is not a formatted state\n        State state = statePayload.castToState();\n        return _isValidState(state);\n    }\n\n    /// @inheritdoc IStateHub\n    function statesAmount() external view returns (uint256) {\n        return _originStates.length;\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestLatestState() external view returns (bytes memory stateData) {\n        // This never underflows, assuming the contract was initialized\n        return suggestState(_nextNonce() - 1);\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestState(uint32 nonce) public view returns (bytes memory stateData) {\n        // This will revert if nonce is out of range\n        bytes32 root = _tree.root(nonce);\n        return _formatOriginState(_originStates[nonce], root, localDomain, nonce);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Initializes the saved states list by inserting a state for an empty Merkle Tree.\n    function _initializeStates() internal {\n        // This should only be called once, when the contract is initialized\n        // This will revert if _tree.roots is non-empty\n        bytes32 savedRoot = _tree.initializeRoots();\n        // Save root for empty merkle _tree with block number and timestamp of initialization\n        _saveState(savedRoot, _toOriginState());\n    }\n\n    /// @dev Inserts leaf into the Merkle Tree and saves the updated origin State.\n    function _insertAndSave(bytes32 leaf) internal {\n        bytes32 newRoot = _tree.insert(leaf);\n        _saveState(newRoot, _toOriginState());\n    }\n\n    /// @dev Saves an updated state of the Origin contract\n    function _saveState(bytes32 root, OriginState memory state) internal {\n        uint32 nonce = _nextNonce();\n        _originStates.push(state);\n        // Emit event with raw state data\n        emit StateSaved(_formatOriginState(state, root, localDomain, nonce));\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns nonce of the next sent message: the amount of saved States so far.\n    /// This always equals to \"total amount of sent messages\" plus 1.\n    function _nextNonce() internal view returns (uint32) {\n        // TODO: consider using more than 32 bits for origin nonces\n        return _originStates.length.toUint32();\n    }\n\n    /// @dev Checks if a state is valid, i.e. if it matches the historical one.\n    /// Reverts, if state refers to another Origin contract.\n    function _isValidState(State state) internal view returns (bool) {\n        // Check if state refers to this contract\n        if (state.origin() != localDomain) revert IncorrectOriginDomain();\n        // Check if nonce exists\n        uint32 nonce = state.nonce();\n        if (nonce \u003e= _originStates.length) return false;\n        // Check if state root matches the historical one\n        if (state.root() != _tree.root(nonce)) return false;\n        // Check if state metadata matches the historical one\n        return _areEqual(state, _originStates[nonce]);\n    }\n\n    // ═════════════════════════════════════════════ STRUCT FORMATTING ═════════════════════════════════════════════════\n\n    /// @dev Returns a formatted payload for a stored OriginState.\n    function _formatOriginState(OriginState memory originState, bytes32 root, uint32 origin, uint32 nonce)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return StateLib.formatState({\n            root_: root,\n            origin_: origin,\n            nonce_: nonce,\n            blockNumber_: originState.blockNumber,\n            timestamp_: originState.timestamp,\n            gasData_: originState.gasData\n        });\n    }\n\n    /// @dev Child contract should implement the logic for getting the current gas data from the gas oracle\n    /// to be saved as part of the Origin State.\n    // solhint-disable-next-line ordering\n    function _fetchGasData() internal view virtual returns (GasData);\n\n    /// @dev Returns a OriginState struct to save in the contract.\n    function _toOriginState() internal view returns (OriginState memory originState) {\n        originState.blockNumber = ChainContext.blockNumber();\n        originState.timestamp = ChainContext.blockTimestamp();\n        originState.gasData = _fetchGasData();\n    }\n\n    /// @dev Checks that a state and its Origin representation are equal.\n    function _areEqual(State state, OriginState memory originState) internal pure returns (bool) {\n        return state.blockNumber() == originState.blockNumber \u0026\u0026 state.timestamp() == originState.timestamp;\n    }\n}\n\n// contracts/Origin.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Origin` contract is used for sending messages to remote chains. It is done\n/// by inserting the message hashes into the Origin Merkle, which makes it possible to\n/// prove that message was sent using the Merkle proof against the Origin Merkle Root. This essentially\n/// compresses the list of messages into a single 32-byte value that needs to be stored on the destination chain.\n/// `Origin` is responsible for the following:\n/// - Formatting the sent message payloads, and inserting their hashes into the Origin Merkle Tree.\n/// - Keeping track of its own historical states (see parent contract `StateHub`).\n/// - Enforcing minimum tip values for sent base messages based on the provided execution requests.\n/// - Distributing the collected tips upon request from a local `AgentManager` contract.\ncontract Origin is StateHub, OriginEvents, InterfaceOrigin {\n    using MemViewLib for bytes;\n    using MessageLib for bytes;\n    using TipsLib for bytes;\n    using TypeCasts for address;\n\n    address public immutable gasOracle;\n\n    modifier onlyRemoteDestination(uint32 destination) {\n        if (destination == localDomain) revert IncorrectDestinationDomain();\n        _;\n    }\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_, address gasOracle_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {\n        gasOracle = gasOracle_;\n    }\n\n    /// @notice Initializes Origin contract:\n    /// - msg.sender is set as contract owner\n    /// - State of \"empty merkle tree\" is saved\n    function initialize() external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize \"states\": state of an \"empty merkle tree\" is saved\n        _initializeStates();\n    }\n\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable onlyRemoteDestination(destination) returns (uint32 messageNonce, bytes32 messageHash) {\n        // Check that content is not too large\n        if (content.length \u003e MAX_CONTENT_BYTES) revert ContentLengthTooBig();\n        // This will revert if msg.value is lower than value of minimum tips\n        Tips tips = _getMinimumTips(destination, paddedRequest, content.length).matchValue(msg.value);\n        Request request = RequestLib.wrapPadded(paddedRequest);\n        // Format the BaseMessage body\n        bytes memory body = BaseMessageLib.formatBaseMessage({\n            sender_: msg.sender.addressToBytes32(),\n            recipient_: recipient,\n            tips_: tips,\n            request_: request,\n            content_: content\n        });\n        // Send the message\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Base, body);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        onlyAgentManager\n        onlyRemoteDestination(destination)\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // AgentManager (checked via modifier) is responsible for constructing the calldata payload correctly.\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Manager, payload);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function withdrawTips(address recipient, uint256 amount) external onlyAgentManager {\n        if (address(this).balance \u003c amount) revert InsufficientEthBalance();\n        (bool success,) = recipient.call{value: amount}(\"\");\n        if (!success) revert EthTransferFailed();\n        emit TipWithdrawalCompleted(recipient, amount);\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue)\n    {\n        return _getMinimumTips(destination, paddedRequest, contentLength).value();\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Sends the given message to the specified destination. Message hash is inserted\n    /// into the Origin Merkle Tree, which will enable message execution on destination chain.\n    function _sendMessage(uint32 destination, uint32 optimisticPeriod, MessageFlag flag, bytes memory body)\n        internal\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // Format the message header\n        messageNonce = _nextNonce();\n        Header header = flag.encodeHeader({\n            origin_: localDomain,\n            nonce_: messageNonce,\n            destination_: destination,\n            optimisticPeriod_: optimisticPeriod\n        });\n        // Format the full message payload\n        bytes memory msgPayload = MessageLib.formatMessage(header, body);\n        // Insert new leaf into the Origin Merkle Tree and save the updated state\n        messageHash = msgPayload.castToMessage().leaf();\n        _insertAndSave(messageHash);\n        // Emit event with message information\n        emit Sent(messageHash, messageNonce, destination, msgPayload);\n        // Update the gas oracle data. We do this after the provided tips are checked so that\n        // the provided message is sent in the event that the gas oracle data is updated to a higher value.\n        InterfaceGasOracle(gasOracle).updateGasData(destination);\n        // TODO: consider doing this before the message is sent, while adjusting GasOracle.getMinimumTips() to\n        // use the pending gas oracle data.\n    }\n\n    /// @dev Returns the minimum tips for sending a message to the given destination with the given request and content.\n    function _getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        internal\n        view\n        returns (Tips)\n    {\n        return\n            TipsLib.wrapPadded(InterfaceGasOracle(gasOracle).getMinimumTips(destination, paddedRequest, contentLength));\n    }\n\n    /// @dev Gets the current gas data from the gas oracle to be saved as part of the Origin State.\n    function _fetchGasData() internal view override returns (GasData) {\n        return GasDataLib.wrapGasData(InterfaceGasOracle(gasOracle).getGasData());\n    }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"","srcMapRuntime":"","abiDefinition":[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"messageHash","type":"bytes32"},{"indexed":true,"internalType":"uint32","name":"nonce","type":"uint32"},{"indexed":true,"internalType":"uint32","name":"destination","type":"uint32"},{"indexed":false,"internalType":"bytes","name":"message","type":"bytes"}],"name":"Sent","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"actor","type":"address"},{"indexed":false,"internalType":"uint256","name":"tip","type":"uint256"}],"name":"TipWithdrawalCompleted","type":"event"}],"userDoc":{"events":{"Sent(bytes32,uint32,uint32,bytes)":{"notice":"Emitted when a new message is sent."},"TipWithdrawalCompleted(address,uint256)":{"notice":"Emitted when a tip withdrawal is completed."}},"kind":"user","methods":{},"notice":"A collection of events emitted by the Origin contract","version":1},"developerDoc":{"events":{"Sent(bytes32,uint32,uint32,bytes)":{"params":{"destination":"Destination domain","message":"Raw bytes of message","messageHash":"Hash of message; the leaf inserted to the Merkle tree for the message","nonce":"Nonce of sent message (starts from 1)"}},"TipWithdrawalCompleted(address,uint256)":{"params":{"actor":"Actor address","tip":"Tip value, denominated in local domain's wei"}}},"kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"nonce\",\"type\":\"uint32\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"destination\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"}],\"name\":\"Sent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"actor\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tip\",\"type\":\"uint256\"}],\"name\":\"TipWithdrawalCompleted\",\"type\":\"event\"}],\"devdoc\":{\"events\":{\"Sent(bytes32,uint32,uint32,bytes)\":{\"params\":{\"destination\":\"Destination domain\",\"message\":\"Raw bytes of message\",\"messageHash\":\"Hash of message; the leaf inserted to the Merkle tree for the message\",\"nonce\":\"Nonce of sent message (starts from 1)\"}},\"TipWithdrawalCompleted(address,uint256)\":{\"params\":{\"actor\":\"Actor address\",\"tip\":\"Tip value, denominated in local domain's wei\"}}},\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"events\":{\"Sent(bytes32,uint32,uint32,bytes)\":{\"notice\":\"Emitted when a new message is sent.\"},\"TipWithdrawalCompleted(address,uint256)\":{\"notice\":\"Emitted when a tip withdrawal is completed.\"}},\"kind\":\"user\",\"methods\":{},\"notice\":\"A collection of events emitted by the Origin contract\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Origin.sol\":\"OriginEvents\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Origin.sol\":{\"keccak256\":\"0x96775924f147f3d1f8df8cdf56731fe52a15af8d8e12e608efb8158c112b18cd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e642a27f5fab3c62b4c02e9754e9e42b1cf2e5381dbea9d3d106d23b7772ebe6\",\"dweb:/ipfs/QmUwn7ZyBvPkjnMuK8ZMSexBUdNQnVtxwyoAyT4DXLQjra\"]}},\"version\":1}"},"hashes":{}},"solidity/Origin.sol:Ownable2StepUpgradeable":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/OriginEvents.sol\n\n/// @notice A collection of events emitted by the Origin contract\nabstract contract OriginEvents {\n    /**\n     * @notice Emitted when a new message is sent.\n     * @param messageHash   Hash of message; the leaf inserted to the Merkle tree for the message\n     * @param nonce         Nonce of sent message (starts from 1)\n     * @param destination   Destination domain\n     * @param message       Raw bytes of message\n     */\n    event Sent(bytes32 indexed messageHash, uint32 indexed nonce, uint32 indexed destination, bytes message);\n\n    /**\n     * @notice Emitted when a tip withdrawal is completed.\n     * @param actor     Actor address\n     * @param tip       Tip value, denominated in local domain's wei\n     */\n    event TipWithdrawalCompleted(address actor, uint256 tip);\n}\n\n// contracts/events/StateHubEvents.sol\n\n/// @notice A collection of events emitted by the StateHub contract\nabstract contract StateHubEvents {\n    /**\n     * @notice Emitted when a new Origin State is saved after a message was sent.\n     * @param state     Raw payload with state data\n     */\n    event StateSaved(bytes state);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n    /**\n     * @notice Check that a given state is valid: matches the historical state of Origin contract.\n     * Note: any Agent including an invalid state in their snapshot will be slashed\n     * upon providing the snapshot and agent signature for it to Origin contract.\n     * @dev Will revert if any of these is true:\n     *  - State payload is not properly formatted.\n     * @param statePayload      Raw payload with state data\n     * @return isValid          Whether the provided state is valid\n     */\n    function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns the amount of saved states so far.\n     * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n     */\n    function statesAmount() external view returns (uint256);\n\n    /**\n     * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @return statePayload     Raw payload with the latest state data\n     */\n    function suggestLatestState() external view returns (bytes memory statePayload);\n\n    /**\n     * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @param nonce             Historical nonce to form a state\n     * @return statePayload     Raw payload with historical state data\n     */\n    function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/InterfaceGasOracle.sol\n\ninterface InterfaceGasOracle {\n    /**\n     * @notice Fetches the latest gas data for the chain from `Destination` contract,\n     * and uses it to update the oracle values for the requested chain.\n     * @param domain    Domain to update the gas data for\n     */\n    function updateGasData(uint32 domain) external;\n\n    /**\n     * @notice Returns the gas data for the local chain.\n     */\n    function getGasData() external view returns (uint256 paddedGasData);\n\n    /**\n     * @notice Returns the gas data for the given domain, in the decoded format.\n     * @param domain        Domain of chain to get gas data for\n     * @return gasPrice     Gas price for the chain (in Wei per gas unit)\n     * @return dataPrice    Calldata price (in Wei per byte of content)\n     * @return execBuffer   Tx fee safety buffer for message execution (in Wei)\n     * @return amortAttCost Amortized cost for attestation submission (in Wei)\n     * @return etherPrice   Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n     * @return markup       Markup for the message execution (in BWAD)\n     */\n    function getDecodedGasData(uint32 domain)\n        external\n        view\n        returns (\n            uint256 gasPrice,\n            uint256 dataPrice,\n            uint256 execBuffer,\n            uint256 amortAttCost,\n            uint256 etherPrice,\n            uint256 markup\n        );\n\n    /**\n     * @notice Returns the minimum tips for sending a message to a given destination.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return paddedTips       Padded encoded minimum tips information\n     */\n    function getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 paddedTips);\n}\n\n// contracts/interfaces/InterfaceOrigin.sol\n\ninterface InterfaceOrigin {\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /**\n     * @notice Send a message to the recipient located on destination domain.\n     * @dev Recipient has to conform to IMessageRecipient interface, otherwise message won't be delivered.\n     * Will revert if any of these is true:\n     * - `destination` is equal to contract's local domain\n     * - `content` length is greater than `MAX_CONTENT_BYTES`\n     * - `msg.value` is lower than value of minimum tips for the given message\n     * @param destination           Domain of destination chain\n     * @param recipient             Address of recipient on destination chain as bytes32\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param paddedRequest         Padded encoded message execution request on destination chain\n     * @param content               Raw bytes content of message\n     * @return messageNonce         Nonce of the sent message\n     * @return messageHash          Hash of the sent message\n     */\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable returns (uint32 messageNonce, bytes32 messageHash);\n\n    /**\n     * @notice Send a manager message to the destination domain.\n     * @dev This could only be called by AgentManager, which takes care of encoding the calldata payload.\n     * Note: (msgOrigin, proofMaturity) security args will be added to payload on the destination chain\n     * so that the AgentManager could verify where the Manager Message came from and how mature is the proof.\n     * Note: function is not payable, as no tips are required for sending a manager message.\n     * Will revert if `destination` is equal to contract's local domain.\n     * @param destination           Domain of destination chain\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param payload               Payload for calling AgentManager on destination chain (with extra security args)\n     */\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        returns (uint32 messageNonce, bytes32 messageHash);\n\n    // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Withdraws locked base message tips to the recipient.\n     * @dev Could only be called by a local AgentManager.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function withdrawTips(address recipient, uint256 amount) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the minimum tips value for sending a message to a given destination.\n     * @dev Using at least `tipsValue` as `msg.value` for `sendBaseMessage()`\n     * will guarantee that the message will be accepted.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return tipsValue        Minimum tips value for a message to be accepted\n     */\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue);\n}\n\n// contracts/libs/Constants.sol\n\n// Here we define common constants to enable their easier reusing later.\n\n// ══════════════════════════════════ MERKLE ═══════════════════════════════════\n/// @dev Height of the Agent Merkle Tree\nuint256 constant AGENT_TREE_HEIGHT = 32;\n/// @dev Height of the Origin Merkle Tree\nuint256 constant ORIGIN_TREE_HEIGHT = 32;\n/// @dev Height of the Snapshot Merkle Tree. Allows up to 64 leafs, e.g. up to 32 states\nuint256 constant SNAPSHOT_TREE_HEIGHT = 6;\n// ══════════════════════════════════ STRUCTS ══════════════════════════════════\n/// @dev See Attestation.sol: (bytes32,bytes32,uint32,uint40,uint40): 32+32+4+5+5\nuint256 constant ATTESTATION_LENGTH = 78;\n/// @dev See GasData.sol: (uint16,uint16,uint16,uint16,uint16,uint16): 2+2+2+2+2+2\nuint256 constant GAS_DATA_LENGTH = 12;\n/// @dev See Receipt.sol: (uint32,uint32,bytes32,bytes32,uint8,address,address,address): 4+4+32+32+1+20+20+20\nuint256 constant RECEIPT_LENGTH = 133;\n/// @dev See State.sol: (bytes32,uint32,uint32,uint40,uint40,GasData): 32+4+4+5+5+len(GasData)\nuint256 constant STATE_LENGTH = 50 + GAS_DATA_LENGTH;\n/// @dev Maximum amount of states in a single snapshot. Each state produces two leafs in the tree\nuint256 constant SNAPSHOT_MAX_STATES = 1 \u003c\u003c (SNAPSHOT_TREE_HEIGHT - 1);\n// ══════════════════════════════════ MESSAGE ══════════════════════════════════\n/// @dev See Header.sol: (uint8,uint32,uint32,uint32,uint32): 1+4+4+4+4\nuint256 constant HEADER_LENGTH = 17;\n/// @dev See Request.sol: (uint96,uint64,uint32): 12+8+4\nuint256 constant REQUEST_LENGTH = 24;\n/// @dev See Tips.sol: (uint64,uint64,uint64,uint64): 8+8+8+8\nuint256 constant TIPS_LENGTH = 32;\n/// @dev The amount of discarded last bits when encoding tip values\nuint256 constant TIPS_GRANULARITY = 32;\n/// @dev Tip values could be only the multiples of TIPS_MULTIPLIER\nuint256 constant TIPS_MULTIPLIER = 1 \u003c\u003c TIPS_GRANULARITY;\n// ══════════════════════════════ STATEMENT SALTS ══════════════════════════════\n/// @dev Salts for signing various statements\nbytes32 constant ATTESTATION_VALID_SALT = keccak256(\"ATTESTATION_VALID_SALT\");\nbytes32 constant ATTESTATION_INVALID_SALT = keccak256(\"ATTESTATION_INVALID_SALT\");\nbytes32 constant RECEIPT_VALID_SALT = keccak256(\"RECEIPT_VALID_SALT\");\nbytes32 constant RECEIPT_INVALID_SALT = keccak256(\"RECEIPT_INVALID_SALT\");\nbytes32 constant SNAPSHOT_VALID_SALT = keccak256(\"SNAPSHOT_VALID_SALT\");\nbytes32 constant STATE_INVALID_SALT = keccak256(\"STATE_INVALID_SALT\");\n// ═════════════════════════════════ PROTOCOL ══════════════════════════════════\n/// @dev Optimistic period for new agent roots in LightManager\nuint32 constant AGENT_ROOT_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Timeout between the agent root could be proposed and resolved in LightManager\nuint32 constant AGENT_ROOT_PROPOSAL_TIMEOUT = 12 hours;\nuint32 constant BONDING_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Amount of time that the Notary will not be considered active after they won a dispute\nuint32 constant DISPUTE_TIMEOUT_NOTARY = 12 hours;\n/// @dev Amount of time without fresh data from Notaries before contract owner can resolve stuck disputes manually\nuint256 constant FRESH_DATA_TIMEOUT = 4 hours;\n/// @dev Maximum bytes per message = 2 KiB (somewhat arbitrarily set to begin)\nuint256 constant MAX_CONTENT_BYTES = 2 * 2 ** 10;\n/// @dev Maximum value for the summit tip that could be set in GasOracle\nuint256 constant MAX_SUMMIT_TIP = 0.01 ether;\n\n// contracts/libs/Errors.sol\n\n// ══════════════════════════════ INVALID CALLER ═══════════════════════════════\n\nerror CallerNotAgentManager();\nerror CallerNotDestination();\nerror CallerNotInbox();\nerror CallerNotSummit();\n\n// ══════════════════════════════ INCORRECT DATA ═══════════════════════════════\n\nerror IncorrectAttestation();\nerror IncorrectAgentDomain();\nerror IncorrectAgentIndex();\nerror IncorrectAgentProof();\nerror IncorrectAgentRoot();\nerror IncorrectDataHash();\nerror IncorrectDestinationDomain();\nerror IncorrectOriginDomain();\nerror IncorrectSnapshotProof();\nerror IncorrectSnapshotRoot();\nerror IncorrectState();\nerror IncorrectStatesAmount();\nerror IncorrectTipsProof();\nerror IncorrectVersionLength();\n\nerror IncorrectNonce();\nerror IncorrectSender();\nerror IncorrectRecipient();\n\nerror FlagOutOfRange();\nerror IndexOutOfRange();\nerror NonceOutOfRange();\n\nerror OutdatedNonce();\n\nerror UnformattedAttestation();\nerror UnformattedAttestationReport();\nerror UnformattedBaseMessage();\nerror UnformattedCallData();\nerror UnformattedCallDataPrefix();\nerror UnformattedMessage();\nerror UnformattedReceipt();\nerror UnformattedReceiptReport();\nerror UnformattedSignature();\nerror UnformattedSnapshot();\nerror UnformattedState();\nerror UnformattedStateReport();\n\n// ═══════════════════════════════ MERKLE TREES ════════════════════════════════\n\nerror LeafNotProven();\nerror MerkleTreeFull();\nerror NotEnoughLeafs();\nerror TreeHeightTooLow();\n\n// ═════════════════════════════ OPTIMISTIC PERIOD ═════════════════════════════\n\nerror BaseClientOptimisticPeriod();\nerror MessageOptimisticPeriod();\nerror SlashAgentOptimisticPeriod();\nerror WithdrawTipsOptimisticPeriod();\nerror ZeroProofMaturity();\n\n// ═══════════════════════════════ AGENT MANAGER ═══════════════════════════════\n\nerror AgentNotGuard();\nerror AgentNotNotary();\n\nerror AgentCantBeAdded();\nerror AgentNotActive();\nerror AgentNotActiveNorUnstaking();\nerror AgentNotFraudulent();\nerror AgentNotUnstaking();\nerror AgentUnknown();\n\nerror AgentRootNotProposed();\nerror AgentRootTimeoutNotOver();\n\nerror NotStuck();\n\nerror DisputeAlreadyResolved();\nerror DisputeNotOpened();\nerror DisputeTimeoutNotOver();\nerror GuardInDispute();\nerror NotaryInDispute();\n\nerror MustBeSynapseDomain();\nerror SynapseDomainForbidden();\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\nerror AlreadyExecuted();\nerror AlreadyFailed();\nerror DuplicatedSnapshotRoot();\nerror IncorrectMagicValue();\nerror GasLimitTooLow();\nerror GasSuppliedTooLow();\n\n// ══════════════════════════════════ ORIGIN ═══════════════════════════════════\n\nerror ContentLengthTooBig();\nerror EthTransferFailed();\nerror InsufficientEthBalance();\n\n// ════════════════════════════════ GAS ORACLE ═════════════════════════════════\n\nerror LocalGasDataNotSet();\nerror RemoteGasDataNotSet();\n\n// ═══════════════════════════════════ TIPS ════════════════════════════════════\n\nerror SummitTipTooHigh();\nerror TipsClaimMoreThanEarned();\nerror TipsClaimZero();\nerror TipsOverflow();\nerror TipsValueTooLow();\n\n// ════════════════════════════════ MEMORY VIEW ════════════════════════════════\n\nerror IndexedTooMuch();\nerror ViewOverrun();\nerror OccupiedMemory();\nerror UnallocatedMemory();\nerror PrecompileOutOfGas();\n\n// ═════════════════════════════════ MULTICALL ═════════════════════════════════\n\nerror MulticallFailed();\n\n// contracts/libs/TypeCasts.sol\n\nlibrary TypeCasts {\n    // alignment preserving cast\n    function addressToBytes32(address addr) internal pure returns (bytes32) {\n        return bytes32(uint256(uint160(addr)));\n    }\n\n    // alignment preserving cast\n    function bytes32ToAddress(bytes32 buf) internal pure returns (address) {\n        return address(uint160(uint256(buf)));\n    }\n}\n\n// contracts/libs/stack/Number.sol\n\n/// Number is a compact representation of uint256, that is fit into 16 bits\n/// with the maximum relative error under 0.4%.\ntype Number is uint16;\n\nusing NumberLib for Number global;\n\n/// # Number\n/// Library for compact representation of uint256 numbers.\n/// - Number is stored using mantissa and exponent, each occupying 8 bits.\n/// - Numbers under 2**8 are stored as `mantissa` with `exponent = 0xFF`.\n/// - Numbers at least 2**8 are approximated as `(256 + mantissa) \u003c\u003c exponent`\n/// \u003e - `0 \u003c= mantissa \u003c 256`\n/// \u003e - `0 \u003c= exponent \u003c= 247` (`256 * 2**248` doesn't fit into uint256)\n/// # Number stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type  | Bytes |\n/// | ---------- | -------- | ----- | ----- |\n/// | (002..001] | mantissa | uint8 | 1     |\n/// | (001..000] | exponent | uint8 | 1     |\n\nlibrary NumberLib {\n    /// @dev Amount of bits to shift to mantissa field\n    uint16 private constant SHIFT_MANTISSA = 8;\n\n    /// @notice For bwad math (binary wad) we use 2**64 as \"wad\" unit.\n    /// @dev We are using not using 10**18 as wad, because it is not stored precisely in NumberLib.\n    uint256 internal constant BWAD_SHIFT = 64;\n    uint256 internal constant BWAD = 1 \u003c\u003c BWAD_SHIFT;\n    /// @notice ~0.1% in bwad units.\n    uint256 internal constant PER_MILLE_SHIFT = BWAD_SHIFT - 10;\n    uint256 internal constant PER_MILLE = 1 \u003c\u003c PER_MILLE_SHIFT;\n\n    /// @notice Compresses uint256 number into 16 bits.\n    function compress(uint256 value) internal pure returns (Number) {\n        // Find `msb` such as `2**msb \u003c= value \u003c 2**(msb + 1)`\n        uint256 msb = mostSignificantBit(value);\n        // We want to preserve 9 bits of precision.\n        // The highest bit is always 1, so we can skip it.\n        // The remaining 8 highest bits are stored as mantissa.\n        if (msb \u003c 8) {\n            // Value is less than 2**8, so we can use value as mantissa with \"-1\" exponent.\n            return _encode(uint8(value), 0xFF);\n        } else {\n            // We use `msb - 8` as exponent otherwise. Note that `exponent \u003e= 0`.\n            unchecked {\n                uint256 exponent = msb - 8;\n                // Shifting right by `msb-8` bits will shift the \"remaining 8 highest bits\" into the 8 lowest bits.\n                // uint8() will truncate the highest bit.\n                return _encode(uint8(value \u003e\u003e exponent), uint8(exponent));\n            }\n        }\n    }\n\n    /// @notice Decompresses 16 bits number into uint256.\n    /// @dev The outcome is an approximation of the original number: `(value - value / 256) \u003c number \u003c= value`.\n    function decompress(Number number) internal pure returns (uint256 value) {\n        // Isolate 8 highest bits as the mantissa.\n        uint256 mantissa = Number.unwrap(number) \u003e\u003e SHIFT_MANTISSA;\n        // This will truncate the highest bits, leaving only the exponent.\n        uint256 exponent = uint8(Number.unwrap(number));\n        if (exponent == 0xFF) {\n            return mantissa;\n        } else {\n            unchecked {\n                return (256 + mantissa) \u003c\u003c (exponent);\n            }\n        }\n    }\n\n    /// @dev Returns the most significant bit of `x`\n    /// https://solidity-by-example.org/bitwise/\n    function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\n        // To find `msb` we determine it bit by bit, starting from the highest one.\n        // `0 \u003c= msb \u003c= 255`, so we start from the highest bit, 1\u003c\u003c7 == 128.\n        // If `x` is at least 2**128, then the highest bit of `x` is at least 128.\n        // solhint-disable no-inline-assembly\n        assembly {\n            // `f` is set to 1\u003c\u003c7 if `x \u003e= 2**128` and to 0 otherwise.\n            let f := shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\n            // If `x \u003e= 2**128` then set `msb` highest bit to 1 and shift `x` right by 128.\n            // Otherwise, `msb` remains 0 and `x` remains unchanged.\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        // `x` is now at most 2**128 - 1. Continue the same way, the next highest bit is 1\u003c\u003c6 == 64.\n        assembly {\n            // `f` is set to 1\u003c\u003c6 if `x \u003e= 2**64` and to 0 otherwise.\n            let f := shl(6, gt(x, 0xFFFFFFFFFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c5 if `x \u003e= 2**32` and to 0 otherwise.\n            let f := shl(5, gt(x, 0xFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c4 if `x \u003e= 2**16` and to 0 otherwise.\n            let f := shl(4, gt(x, 0xFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c3 if `x \u003e= 2**8` and to 0 otherwise.\n            let f := shl(3, gt(x, 0xFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c2 if `x \u003e= 2**4` and to 0 otherwise.\n            let f := shl(2, gt(x, 0xF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c1 if `x \u003e= 2**2` and to 0 otherwise.\n            let f := shl(1, gt(x, 0x3))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1 if `x \u003e= 2**1` and to 0 otherwise.\n            let f := gt(x, 0x1)\n            msb := or(msb, f)\n        }\n    }\n\n    /// @dev Wraps (mantissa, exponent) pair into Number.\n    function _encode(uint8 mantissa, uint8 exponent) private pure returns (Number) {\n        // Casts below are upcasts, so they are safe.\n        return Number.wrap(uint16(mantissa) \u003c\u003c SHIFT_MANTISSA | uint16(exponent));\n    }\n}\n\n// contracts/libs/stack/Request.sol\n\n/// Request is encoded data with \"message execution request\".\ntype Request is uint192;\n\nusing RequestLib for Request global;\n\n/// Library for formatting _the request part_ of _the base messages_.\n/// - Request represents a message sender requirements for the message execution on the destination chain.\n/// - Request occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n/// \u003e gasDrop field is included for future compatibility and is ignored at the moment.\n///\n/// # Request stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type   | Bytes | Description                                          |\n/// | ---------- | -------- | ------ | ----- | ---------------------------------------------------- |\n/// | (024..012] | gasDrop  | uint96 | 12    | Minimum amount of gas token to drop to the recipient |\n/// | (012..004] | gasLimit | uint64 | 8     | Minimum amount of gas units to supply for execution  |\n/// | (004..000] | version  | uint32 | 4     | Base message version to pass to the recipient        |\n\nlibrary RequestLib {\n    /// @dev Amount of bits to shift to gasDrop field\n    uint192 private constant SHIFT_GAS_DROP = 12 * 8;\n    /// @dev Amount of bits to shift to gasLimit field\n    uint192 private constant SHIFT_GAS_LIMIT = 4 * 8;\n\n    /// @notice Returns an encoded request with the given fields\n    /// @param gasDrop_     Minimum amount of gas token to drop to the recipient (ignored at the moment)\n    /// @param gasLimit_    Minimum amount of gas units to supply for execution\n    /// @param version_     Base message version to pass to the recipient\n    function encodeRequest(uint96 gasDrop_, uint64 gasLimit_, uint32 version_) internal pure returns (Request) {\n        // Casts below are upcasts, so they are safe\n        return Request.wrap(uint192(gasDrop_) \u003c\u003c SHIFT_GAS_DROP | uint192(gasLimit_) \u003c\u003c SHIFT_GAS_LIMIT | version_);\n    }\n\n    /// @notice Wraps the padded encoded request into a Request-typed value.\n    /// @dev The \"padded\" request is simply an encoded request casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded requests\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedRequest) internal pure returns (Request) {\n        // Casting to uint192 will truncate the highest bits, which is the behavior we want\n        return Request.wrap(uint192(paddedRequest));\n    }\n\n    /// @notice Returns the requested of gas token to drop to the recipient.\n    function gasDrop(Request request) internal pure returns (uint96) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return uint96(Request.unwrap(request) \u003e\u003e SHIFT_GAS_DROP);\n    }\n\n    /// @notice Returns the requested minimum amount of gas units to supply for execution.\n    function gasLimit(Request request) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Request.unwrap(request) \u003e\u003e SHIFT_GAS_LIMIT);\n    }\n\n    /// @notice Returns the requested base message version to pass to the recipient.\n    function version(Request request) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Request.unwrap(request));\n    }\n}\n\n// node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        require(value \u003c= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        require(value \u003c= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        require(value \u003c= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value \u003c= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        require(value \u003c= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        require(value \u003c= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        require(value \u003c= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        require(value \u003c= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        require(value \u003c= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        require(value \u003c= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        require(value \u003c= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        require(value \u003c= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        require(value \u003c= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        require(value \u003c= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        require(value \u003c= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value \u003c= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        require(value \u003c= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        require(value \u003c= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        require(value \u003c= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value \u003c= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        require(value \u003c= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        require(value \u003c= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        require(value \u003c= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value \u003c= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        require(value \u003c= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        require(value \u003c= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        require(value \u003c= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value \u003c= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        require(value \u003c= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value \u003c= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value \u003c= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     *\n     * _Available since v3.0._\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value \u003e= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     *\n     * _Available since v3.0._\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value \u003c= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     *\n     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length \u003e 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance \u003e= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance \u003e= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length \u003e 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n\n// contracts/base/MultiCallable.sol\n\n/// @notice Collection of Multicall utilities. Fork of Multicall3:\n/// https://github.com/mds1/multicall/blob/master/src/Multicall3.sol\nabstract contract MultiCallable {\n    struct Call {\n        bool allowFailure;\n        bytes callData;\n    }\n\n    struct Result {\n        bool success;\n        bytes returnData;\n    }\n\n    /// @notice Aggregates a few calls to this contract into one multicall without modifying `msg.sender`.\n    function multicall(Call[] calldata calls) external returns (Result[] memory callResults) {\n        uint256 amount = calls.length;\n        callResults = new Result[](amount);\n        Call calldata call_;\n        for (uint256 i = 0; i \u003c amount;) {\n            call_ = calls[i];\n            Result memory result = callResults[i];\n            // We perform a delegate call to ourselves here. Delegate call does not modify `msg.sender`, so\n            // this will have the same effect as if `msg.sender` performed all the calls themselves one by one.\n            // solhint-disable-next-line avoid-low-level-calls\n            (result.success, result.returnData) = address(this).delegatecall(call_.callData);\n            // solhint-disable-next-line no-inline-assembly\n            assembly {\n                // Revert if the call fails and failure is not allowed\n                // `allowFailure := calldataload(call_)` and `success := mload(result)`\n                if iszero(or(calldataload(call_), mload(result))) {\n                    // Revert with `0x4d6a2328` (function selector for `MulticallFailed()`)\n                    mstore(0x00, 0x4d6a232800000000000000000000000000000000000000000000000000000000)\n                    revert(0x00, 0x04)\n                }\n            }\n            unchecked {\n                ++i;\n            }\n        }\n    }\n}\n\n// contracts/base/Version.sol\n\n/**\n * @title Versioned\n * @notice Version getter for contracts. Doesn't use any storage slots, meaning\n * it will never cause any troubles with the upgradeable contracts. For instance, this contract\n * can be added or removed from the inheritance chain without shifting the storage layout.\n */\nabstract contract Versioned {\n    /**\n     * @notice Struct that is mimicking the storage layout of a string with 32 bytes or less.\n     * Length is limited by 32, so the whole string payload takes two memory words:\n     * @param length    String length\n     * @param data      String characters\n     */\n    struct _ShortString {\n        uint256 length;\n        bytes32 data;\n    }\n\n    /// @dev Length of the \"version string\"\n    uint256 private immutable _length;\n    /// @dev Bytes representation of the \"version string\".\n    /// Strings with length over 32 are not supported!\n    bytes32 private immutable _data;\n\n    constructor(string memory version_) {\n        _length = bytes(version_).length;\n        if (_length \u003e 32) revert IncorrectVersionLength();\n        // bytes32 is left-aligned =\u003e this will store the byte representation of the string\n        // with the trailing zeroes to complete the 32-byte word\n        _data = bytes32(bytes(version_));\n    }\n\n    function version() external view returns (string memory versionString) {\n        // Load the immutable values to form the version string\n        _ShortString memory str = _ShortString(_length, _data);\n        // The only way to do this cast is doing some dirty assembly\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            versionString := str\n        }\n    }\n}\n\n// contracts/libs/ChainContext.sol\n\n/// @notice Library for accessing chain context variables as tightly packed integers.\n/// Messaging contracts should rely on this library for accessing chain context variables\n/// instead of doing the casting themselves.\nlibrary ChainContext {\n    using SafeCast for uint256;\n\n    /// @notice Returns the current block number as uint40.\n    /// @dev Reverts if block number is greater than 40 bits, which is not supposed to happen\n    /// until the block.timestamp overflows (assuming block time is at least 1 second).\n    function blockNumber() internal view returns (uint40) {\n        return block.number.toUint40();\n    }\n\n    /// @notice Returns the current block timestamp as uint40.\n    /// @dev Reverts if block timestamp is greater than 40 bits, which is\n    /// supposed to happen approximately in year 36835.\n    function blockTimestamp() internal view returns (uint40) {\n        return block.timestamp.toUint40();\n    }\n\n    /// @notice Returns the chain id as uint32.\n    /// @dev Reverts if chain id is greater than 32 bits, which is not\n    /// supposed to happen in production.\n    function chainId() internal view returns (uint32) {\n        return block.chainid.toUint32();\n    }\n}\n\n// contracts/libs/Structures.sol\n\n// Here we define common enums and structures to enable their easier reusing later.\n\n// ═══════════════════════════════ AGENT STATUS ════════════════════════════════\n\n/// @dev Potential statuses for the off-chain bonded agent:\n/// - Unknown: never provided a bond =\u003e signature not valid\n/// - Active: has a bond in BondingManager =\u003e signature valid\n/// - Unstaking: has a bond in BondingManager, initiated the unstaking =\u003e signature not valid\n/// - Resting: used to have a bond in BondingManager, successfully unstaked =\u003e signature not valid\n/// - Fraudulent: proven to commit fraud, value in Merkle Tree not updated =\u003e signature not valid\n/// - Slashed: proven to commit fraud, value in Merkle Tree was updated =\u003e signature not valid\n/// Unstaked agent could later be added back to THE SAME domain by staking a bond again.\n/// Honest agent: Unknown -\u003e Active -\u003e unstaking -\u003e Resting -\u003e Active ...\n/// Malicious agent: Unknown -\u003e Active -\u003e Fraudulent -\u003e Slashed\n/// Malicious agent: Unknown -\u003e Active -\u003e Unstaking -\u003e Fraudulent -\u003e Slashed\nenum AgentFlag {\n    Unknown,\n    Active,\n    Unstaking,\n    Resting,\n    Fraudulent,\n    Slashed\n}\n\n/// @notice Struct for storing an agent in the BondingManager contract.\nstruct AgentStatus {\n    AgentFlag flag;\n    uint32 domain;\n    uint32 index;\n}\n// 184 bits available for tight packing\n\nusing StructureUtils for AgentStatus global;\n\n/// @notice Potential statuses of an agent in terms of being in dispute\n/// - None: agent is not in dispute\n/// - Pending: agent is in unresolved dispute\n/// - Slashed: agent was in dispute that lead to agent being slashed\n/// Note: agent who won the dispute has their status reset to None\nenum DisputeFlag {\n    None,\n    Pending,\n    Slashed\n}\n\n/// @notice Struct for storing dispute status of an agent.\n/// @param flag         Dispute flag: None/Pending/Slashed.\n/// @param openedAt     Timestamp when the latest agent dispute was opened (zero if not opened).\n/// @param resolvedAt   Timestamp when the latest agent dispute was resolved (zero if not resolved).\nstruct DisputeStatus {\n    DisputeFlag flag;\n    uint40 openedAt;\n    uint40 resolvedAt;\n}\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\n/// @notice Struct representing the status of Destination contract.\n/// @param snapRootTime     Timestamp when latest snapshot root was accepted\n/// @param agentRootTime    Timestamp when latest agent root was accepted\n/// @param notaryIndex      Index of Notary who signed the latest agent root\nstruct DestinationStatus {\n    uint40 snapRootTime;\n    uint40 agentRootTime;\n    uint32 notaryIndex;\n}\n\n// ═══════════════════════════════ EXECUTION HUB ═══════════════════════════════\n\n/// @notice Potential statuses of the message in Execution Hub.\n/// - None: there hasn't been a valid attempt to execute the message yet\n/// - Failed: there was a valid attempt to execute the message, but recipient reverted\n/// - Success: there was a valid attempt to execute the message, and recipient did not revert\n/// Note: message can be executed until its status is Success\nenum MessageStatus {\n    None,\n    Failed,\n    Success\n}\n\nlibrary StructureUtils {\n    /// @notice Checks that Agent is Active\n    function verifyActive(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active) {\n            revert AgentNotActive();\n        }\n    }\n\n    /// @notice Checks that Agent is Unstaking\n    function verifyUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Unstaking) {\n            revert AgentNotUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Active or Unstaking\n    function verifyActiveUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active \u0026\u0026 status.flag != AgentFlag.Unstaking) {\n            revert AgentNotActiveNorUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Fraudulent\n    function verifyFraudulent(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Fraudulent) {\n            revert AgentNotFraudulent();\n        }\n    }\n\n    /// @notice Checks that Agent is not Unknown\n    function verifyKnown(AgentStatus memory status) internal pure {\n        if (status.flag == AgentFlag.Unknown) {\n            revert AgentUnknown();\n        }\n    }\n}\n\n// contracts/libs/memory/MemView.sol\n\n/// @dev MemView is an untyped view over a portion of memory to be used instead of `bytes memory`\ntype MemView is uint256;\n\n/// @dev Attach library functions to MemView\nusing MemViewLib for MemView global;\n\n/// @notice Library for operations with the memory views.\n/// Forked from https://github.com/summa-tx/memview-sol with several breaking changes:\n/// - The codebase is ported to Solidity 0.8\n/// - Custom errors are added\n/// - The runtime type checking is replaced with compile-time check provided by User-Defined Value Types\n///   https://docs.soliditylang.org/en/latest/types.html#user-defined-value-types\n/// - uint256 is used as the underlying type for the \"memory view\" instead of bytes29.\n///   It is wrapped into MemView custom type in order not to be confused with actual integers.\n/// - Therefore the \"type\" field is discarded, allowing to allocate 16 bytes for both view location and length\n/// - The documentation is expanded\n/// - Library functions unused by the rest of the codebase are removed\n//  - Very pretty code separators are added :)\nlibrary MemViewLib {\n    /// @notice Stack layout for uint256 (from highest bits to lowest)\n    /// (32 .. 16]      loc     16 bytes    Memory address of underlying bytes\n    /// (16 .. 00]      len     16 bytes    Length of underlying bytes\n\n    // ═══════════════════════════════════════════ BUILDING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Instantiate a new untyped memory view. This should generally not be called directly.\n     * Prefer `ref` wherever possible.\n     * @param loc_          The memory address\n     * @param len_          The length\n     * @return The new view with the specified location and length\n     */\n    function build(uint256 loc_, uint256 len_) internal pure returns (MemView) {\n        uint256 end_ = loc_ + len_;\n        // Make sure that a view is not constructed that points to unallocated memory\n        // as this could be indicative of a buffer overflow attack\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            if gt(end_, mload(0x40)) { end_ := 0 }\n        }\n        if (end_ == 0) {\n            revert UnallocatedMemory();\n        }\n        return _unsafeBuildUnchecked(loc_, len_);\n    }\n\n    /**\n     * @notice Instantiate a memory view from a byte array.\n     * @dev Note that due to Solidity memory representation, it is not possible to\n     * implement a deref, as the `bytes` type stores its len in memory.\n     * @param arr           The byte array\n     * @return The memory view over the provided byte array\n     */\n    function ref(bytes memory arr) internal pure returns (MemView) {\n        uint256 len_ = arr.length;\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 loc_;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // We add 0x20, so that the view starts exactly where the array data starts\n            loc_ := add(arr, 0x20)\n        }\n        return build(loc_, len_);\n    }\n\n    // ════════════════════════════════════════════ CLONING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to the new memory.\n     * @param memView       The memory view\n     * @return arr          The cloned byte array\n     */\n    function clone(MemView memView) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        unchecked {\n            _unsafeCopyTo(memView, ptr + 0x20);\n        }\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 len_ = memView.len();\n        uint256 footprint_ = memView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    /**\n     * @notice Copies all views, joins them into a new bytearray.\n     * @param memViews      The memory views\n     * @return arr          The new byte array with joined data behind the given views\n     */\n    function join(MemView[] memory memViews) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        MemView newView;\n        unchecked {\n            newView = _unsafeJoin(memViews, ptr + 0x20);\n        }\n        uint256 len_ = newView.len();\n        uint256 footprint_ = newView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    // ══════════════════════════════════════════ INSPECTING MEMORY VIEW ═══════════════════════════════════════════════\n\n    /**\n     * @notice Returns the memory address of the underlying bytes.\n     * @param memView       The memory view\n     * @return loc_         The memory address\n     */\n    function loc(MemView memView) internal pure returns (uint256 loc_) {\n        // loc is stored in the highest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u003e\u003e 128;\n    }\n\n    /**\n     * @notice Returns the number of bytes of the view.\n     * @param memView       The memory view\n     * @return len_         The length of the view\n     */\n    function len(MemView memView) internal pure returns (uint256 len_) {\n        // len is stored in the lowest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u0026 type(uint128).max;\n    }\n\n    /**\n     * @notice Returns the endpoint of `memView`.\n     * @param memView       The memory view\n     * @return end_         The endpoint of `memView`\n     */\n    function end(MemView memView) internal pure returns (uint256 end_) {\n        // The endpoint never overflows uint128, let alone uint256, so we could use unchecked math here\n        unchecked {\n            return memView.loc() + memView.len();\n        }\n    }\n\n    /**\n     * @notice Returns the number of memory words this memory view occupies, rounded up.\n     * @param memView       The memory view\n     * @return words_       The number of memory words\n     */\n    function words(MemView memView) internal pure returns (uint256 words_) {\n        // returning ceil(length / 32.0)\n        unchecked {\n            return (memView.len() + 31) \u003e\u003e 5;\n        }\n    }\n\n    /**\n     * @notice Returns the in-memory footprint of a fresh copy of the view.\n     * @param memView       The memory view\n     * @return footprint_   The in-memory footprint of a fresh copy of the view.\n     */\n    function footprint(MemView memView) internal pure returns (uint256 footprint_) {\n        // words() * 32\n        return memView.words() \u003c\u003c 5;\n    }\n\n    // ════════════════════════════════════════════ HASHING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the keccak256 hash of the underlying memory\n     * @param memView       The memory view\n     * @return digest       The keccak256 hash of the underlying memory\n     */\n    function keccak(MemView memView) internal pure returns (bytes32 digest) {\n        uint256 loc_ = memView.loc();\n        uint256 len_ = memView.len();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            digest := keccak256(loc_, len_)\n        }\n    }\n\n    /**\n     * @notice Adds a salt to the keccak256 hash of the underlying data and returns the keccak256 hash of the\n     * resulting data.\n     * @param memView       The memory view\n     * @return digestSalted keccak256(salt, keccak256(memView))\n     */\n    function keccakSalted(MemView memView, bytes32 salt) internal pure returns (bytes32 digestSalted) {\n        return keccak256(bytes.concat(salt, memView.keccak()));\n    }\n\n    // ════════════════════════════════════════════ SLICING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Safe slicing without memory modification.\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the given index\n     */\n    function slice(MemView memView, uint256 index_, uint256 len_) internal pure returns (MemView) {\n        uint256 loc_ = memView.loc();\n        // Ensure it doesn't overrun the view\n        if (loc_ + index_ + len_ \u003e memView.end()) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // loc_ + index_ \u003c= memView.end()\n            return build({loc_: loc_ + index_, len_: len_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing bytes from `index` to end(memView).\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @return The new view for the slice starting from the given index until the initial view endpoint\n     */\n    function sliceFrom(MemView memView, uint256 index_) internal pure returns (MemView) {\n        uint256 len_ = memView.len();\n        // Ensure it doesn't overrun the view\n        if (index_ \u003e len_) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // index_ \u003c= len_ =\u003e memView.loc() + index_ \u003c= memView.loc() + memView.len() == memView.end()\n            return build({loc_: memView.loc() + index_, len_: len_ - index_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the first `len` bytes.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the initial view beginning\n     */\n    function prefix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        return memView.slice({index_: 0, len_: len_});\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the last `len` byte.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length until the initial view endpoint\n     */\n    function postfix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        uint256 viewLen = memView.len();\n        // Ensure it doesn't overrun the view\n        if (len_ \u003e viewLen) {\n            revert ViewOverrun();\n        }\n        // Could do the unchecked math due to the check above\n        uint256 index_;\n        unchecked {\n            index_ = viewLen - len_;\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // len_ \u003c= memView.len() =\u003e memView.loc() \u003c= loc_ \u003c= memView.end()\n            return build({loc_: memView.loc() + viewLen - len_, len_: len_});\n        }\n    }\n\n    // ═══════════════════════════════════════════ INDEXING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Load up to 32 bytes from the view onto the stack.\n     * @dev Returns a bytes32 with only the `bytes_` HIGHEST bytes set.\n     * This can be immediately cast to a smaller fixed-length byte array.\n     * To automatically cast to an integer, use `indexUint`.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return result       The 32 byte result having only `bytes_` highest bytes set\n     */\n    function index(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (bytes32 result) {\n        if (bytes_ == 0) {\n            return bytes32(0);\n        }\n        // Can't load more than 32 bytes to the stack in one go\n        if (bytes_ \u003e 32) {\n            revert IndexedTooMuch();\n        }\n        // The last indexed byte should be within view boundaries\n        if (index_ + bytes_ \u003e memView.len()) {\n            revert ViewOverrun();\n        }\n        uint256 bitLength = bytes_ \u003c\u003c 3; // bytes_ * 8\n        uint256 loc_ = memView.loc();\n        // Get a mask with `bitLength` highest bits set\n        uint256 mask;\n        // 0x800...00 binary representation is 100...00\n        // sar stands for \"signed arithmetic shift\": https://en.wikipedia.org/wiki/Arithmetic_shift\n        // sar(N-1, 100...00) = 11...100..00, with exactly N highest bits set to 1\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            mask := sar(sub(bitLength, 1), 0x8000000000000000000000000000000000000000000000000000000000000000)\n        }\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load a full word using index offset, and apply mask to ignore non-relevant bytes\n            result := and(mload(add(loc_, index_)), mask)\n        }\n    }\n\n    /**\n     * @notice Parse an unsigned integer from the view at `index`.\n     * @dev Requires that the view have \u003e= `bytes_` bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return The unsigned integer\n     */\n    function indexUint(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (uint256) {\n        bytes32 indexedBytes = memView.index(index_, bytes_);\n        // `index()` returns left-aligned `bytes_`, while integers are right-aligned\n        // Shifting here to right-align with the full 32 bytes word: need to shift right `(32 - bytes_)` bytes\n        unchecked {\n            // memView.index() reverts when bytes_ \u003e 32, thus unchecked math\n            return uint256(indexedBytes) \u003e\u003e ((32 - bytes_) \u003c\u003c 3);\n        }\n    }\n\n    /**\n     * @notice Parse an address from the view at `index`.\n     * @dev Requires that the view have \u003e= 20 bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @return The address\n     */\n    function indexAddress(MemView memView, uint256 index_) internal pure returns (address) {\n        // index 20 bytes as `uint160`, and then cast to `address`\n        return address(uint160(memView.indexUint(index_, 20)));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns a memory view over the specified memory location\n    /// without checking if it points to unallocated memory.\n    function _unsafeBuildUnchecked(uint256 loc_, uint256 len_) private pure returns (MemView) {\n        // There is no scenario where loc or len would overflow uint128, so we omit this check.\n        // We use the highest 128 bits to encode the location and the lowest 128 bits to encode the length.\n        return MemView.wrap((loc_ \u003c\u003c 128) | len_);\n    }\n\n    /**\n     * @notice Copy the view to a location, return an unsafe memory reference\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memView       The memory view\n     * @param newLoc        The new location to copy the underlying view data\n     * @return The memory view over the unsafe memory with the copied underlying data\n     */\n    function _unsafeCopyTo(MemView memView, uint256 newLoc) private view returns (MemView) {\n        uint256 len_ = memView.len();\n        uint256 oldLoc = memView.loc();\n\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (newLoc \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        bool res;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // use the identity precompile (0x04) to copy\n            res := staticcall(gas(), 0x04, oldLoc, len_, newLoc, len_)\n        }\n        if (!res) revert PrecompileOutOfGas();\n        return _unsafeBuildUnchecked({loc_: newLoc, len_: len_});\n    }\n\n    /**\n     * @notice Join the views in memory, return an unsafe reference to the memory.\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memViews      The memory views\n     * @return The conjoined view pointing to the new memory\n     */\n    function _unsafeJoin(MemView[] memory memViews, uint256 location) private view returns (MemView) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (location \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        // Copy the views to the specified location one by one, by tracking the amount of copied bytes so far\n        uint256 offset = 0;\n        for (uint256 i = 0; i \u003c memViews.length;) {\n            MemView memView = memViews[i];\n            // We can use the unchecked math here as location + sum(view.length) will never overflow uint256\n            unchecked {\n                _unsafeCopyTo(memView, location + offset);\n                offset += memView.len();\n                ++i;\n            }\n        }\n        return _unsafeBuildUnchecked({loc_: location, len_: offset});\n    }\n}\n\n// contracts/libs/merkle/MerkleMath.sol\n\nlibrary MerkleMath {\n    // ═════════════════════════════════════════ BASIC MERKLE CALCULATIONS ═════════════════════════════════════════════\n\n    /**\n     * @notice Calculates the merkle root for the given leaf and merkle proof.\n     * @dev Will revert if proof length exceeds the tree height.\n     * @param index     Index of `leaf` in tree\n     * @param leaf      Leaf of the merkle tree\n     * @param proof     Proof of inclusion of `leaf` in the tree\n     * @param height    Height of the merkle tree\n     * @return root_    Calculated Merkle Root\n     */\n    function proofRoot(uint256 index, bytes32 leaf, bytes32[] memory proof, uint256 height)\n        internal\n        pure\n        returns (bytes32 root_)\n    {\n        // Proof length could not exceed the tree height\n        uint256 proofLen = proof.length;\n        if (proofLen \u003e height) revert TreeHeightTooLow();\n        root_ = leaf;\n        /// @dev Apply unchecked to all ++h operations\n        unchecked {\n            // Go up the tree levels from the leaf following the proof\n            for (uint256 h = 0; h \u003c proofLen; ++h) {\n                // Get a sibling node on current level: this is proof[h]\n                root_ = getParent(root_, proof[h], index, h);\n            }\n            // Go up to the root: the remaining siblings are EMPTY\n            for (uint256 h = proofLen; h \u003c height; ++h) {\n                root_ = getParent(root_, bytes32(0), index, h);\n            }\n        }\n    }\n\n    /**\n     * @notice Calculates the parent of a node on the path from one of the leafs to root.\n     * @param node          Node on a path from tree leaf to root\n     * @param sibling       Sibling for a given node\n     * @param leafIndex     Index of the tree leaf\n     * @param nodeHeight    \"Level height\" for `node` (ZERO for leafs, ORIGIN_TREE_HEIGHT for root)\n     */\n    function getParent(bytes32 node, bytes32 sibling, uint256 leafIndex, uint256 nodeHeight)\n        internal\n        pure\n        returns (bytes32 parent)\n    {\n        // Index for `node` on its \"tree level\" is (leafIndex / 2**height)\n        // \"Left child\" has even index, \"right child\" has odd index\n        if ((leafIndex \u003e\u003e nodeHeight) \u0026 1 == 0) {\n            // Left child\n            return getParent(node, sibling);\n        } else {\n            // Right child\n            return getParent(sibling, node);\n        }\n    }\n\n    /// @notice Calculates the parent of tow nodes in the merkle tree.\n    /// @dev We use implementation with H(0,0) = 0\n    /// This makes EVERY empty node in the tree equal to ZERO,\n    /// saving us from storing H(0,0), H(H(0,0), H(0, 0)), and so on\n    /// @param leftChild    Left child of the calculated node\n    /// @param rightChild   Right child of the calculated node\n    /// @return parent      Value for the node having above mentioned children\n    function getParent(bytes32 leftChild, bytes32 rightChild) internal pure returns (bytes32 parent) {\n        if (leftChild == bytes32(0) \u0026\u0026 rightChild == bytes32(0)) {\n            return 0;\n        } else {\n            return keccak256(bytes.concat(leftChild, rightChild));\n        }\n    }\n\n    // ════════════════════════════════ ROOT/PROOF CALCULATION FOR A LIST OF LEAFS ═════════════════════════════════════\n\n    /**\n     * @notice Calculates merkle root for a list of given leafs.\n     * Merkle Tree is constructed by padding the list with ZERO values for leafs until list length is `2**height`.\n     * Merkle Root is calculated for the constructed tree, and then saved in `leafs[0]`.\n     * \u003e Note:\n     * \u003e - `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * \u003e - Caller is expected not to reuse `hashes` list after the call, and only use `leafs[0]` value,\n     * which is guaranteed to contain the calculated merkle root.\n     * \u003e - root is calculated using the `H(0,0) = 0` Merkle Tree implementation. See MerkleTree.sol for details.\n     * @dev Amount of leaves should be at most `2**height`\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param height    Height of the Merkle Tree to construct\n     */\n    function calculateRoot(bytes32[] memory hashes, uint256 height) internal pure {\n        uint256 levelLength = hashes.length;\n        // Amount of hashes could not exceed amount of leafs in tree with the given height\n        if (levelLength \u003e (1 \u003c\u003c height)) revert TreeHeightTooLow();\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\": the amount of iterations for the for loop above.\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n            }\n        }\n    }\n\n    /**\n     * @notice Generates a proof of inclusion of a leaf in the list. If the requested index is outside\n     * of the list range, generates a proof of inclusion for an empty leaf (proof of non-inclusion).\n     * The Merkle Tree is constructed by padding the list with ZERO values until list length is a power of two\n     * __AND__ index is in the extended list range. For example:\n     *  - `hashes.length == 6` and `0 \u003c= index \u003c= 7` will \"extend\" the list to 8 entries.\n     *  - `hashes.length == 6` and `7 \u003c index \u003c= 15` will \"extend\" the list to 16 entries.\n     * \u003e Note: `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * Caller is expected not to reuse `hashes` list after the call.\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param index     Leaf index to generate the proof for\n     * @return proof    Generated merkle proof\n     */\n    function calculateProof(bytes32[] memory hashes, uint256 index) internal pure returns (bytes32[] memory proof) {\n        // Use only meaningful values for the shortened proof\n        // Check if index is within the list range (we want to generates proofs for outside leafs as well)\n        uint256 height = getHeight(index \u003c hashes.length ? hashes.length : (index + 1));\n        proof = new bytes32[](height);\n        uint256 levelLength = hashes.length;\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Use sibling for the merkle proof; `index^1` is index of our sibling\n                proof[h] = (index ^ 1 \u003c levelLength) ? hashes[index ^ 1] : bytes32(0);\n\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\"\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n                // Traverse to parent node\n                index \u003e\u003e= 1;\n            }\n        }\n    }\n\n    /// @notice Returns the height of the tree having a given amount of leafs.\n    function getHeight(uint256 leafs) internal pure returns (uint256 height) {\n        uint256 amount = 1;\n        while (amount \u003c leafs) {\n            unchecked {\n                ++height;\n            }\n            amount \u003c\u003c= 1;\n        }\n    }\n}\n\n// contracts/libs/stack/GasData.sol\n\n/// GasData in encoded data with \"basic information about gas prices\" for some chain.\ntype GasData is uint96;\n\nusing GasDataLib for GasData global;\n\n/// ChainGas is encoded data with given chain's \"basic information about gas prices\".\ntype ChainGas is uint128;\n\nusing GasDataLib for ChainGas global;\n\n/// Library for encoding and decoding GasData and ChainGas structs.\n/// # GasData\n/// `GasData` is a struct to store the \"basic information about gas prices\", that could\n/// be later used to approximate the cost of a message execution, and thus derive the\n/// minimal tip values for sending a message to the chain.\n/// \u003e - `GasData` is supposed to be cached by `GasOracle` contract, allowing to store the\n/// \u003e approximates instead of the exact values, and thus save on storage costs.\n/// \u003e - For instance, if `GasOracle` only updates the values on +- 10% change, having an\n/// \u003e 0.4% error on the approximates would be acceptable.\n/// `GasData` is supposed to be included in the Origin's state, which are synced across\n/// chains using Agent-signed snapshots and attestations.\n/// ## GasData stack layout (from highest bits to lowest)\n///\n/// | Position   | Field        | Type   | Bytes | Description                                         |\n/// | ---------- | ------------ | ------ | ----- | --------------------------------------------------- |\n/// | (012..010] | gasPrice     | uint16 | 2     | Gas price for the chain (in Wei per gas unit)       |\n/// | (010..008] | dataPrice    | uint16 | 2     | Calldata price (in Wei per byte of content)         |\n/// | (008..006] | execBuffer   | uint16 | 2     | Tx fee safety buffer for message execution (in Wei) |\n/// | (006..004] | amortAttCost | uint16 | 2     | Amortized cost for attestation submission (in Wei)  |\n/// | (004..002] | etherPrice   | uint16 | 2     | Chain's Ether Price / Mainnet Ether Price (in BWAD) |\n/// | (002..000] | markup       | uint16 | 2     | Markup for the message execution (in BWAD)          |\n/// \u003e See Number.sol for more details on `Number` type and BWAD (binary WAD) math.\n///\n/// ## ChainGas stack layout (from highest bits to lowest)\n///\n/// | Position   | Field   | Type   | Bytes | Description      |\n/// | ---------- | ------- | ------ | ----- | ---------------- |\n/// | (016..004] | gasData | uint96 | 12    | Chain's gas data |\n/// | (004..000] | domain  | uint32 | 4     | Chain's domain   |\nlibrary GasDataLib {\n    /// @dev Amount of bits to shift to gasPrice field\n    uint96 private constant SHIFT_GAS_PRICE = 10 * 8;\n    /// @dev Amount of bits to shift to dataPrice field\n    uint96 private constant SHIFT_DATA_PRICE = 8 * 8;\n    /// @dev Amount of bits to shift to execBuffer field\n    uint96 private constant SHIFT_EXEC_BUFFER = 6 * 8;\n    /// @dev Amount of bits to shift to amortAttCost field\n    uint96 private constant SHIFT_AMORT_ATT_COST = 4 * 8;\n    /// @dev Amount of bits to shift to etherPrice field\n    uint96 private constant SHIFT_ETHER_PRICE = 2 * 8;\n\n    /// @dev Amount of bits to shift to gasData field\n    uint128 private constant SHIFT_GAS_DATA = 4 * 8;\n\n    // ═════════════════════════════════════════════════ GAS DATA ══════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded GasData struct with the given fields.\n    /// @param gasPrice_        Gas price for the chain (in Wei per gas unit)\n    /// @param dataPrice_       Calldata price (in Wei per byte of content)\n    /// @param execBuffer_      Tx fee safety buffer for message execution (in Wei)\n    /// @param amortAttCost_    Amortized cost for attestation submission (in Wei)\n    /// @param etherPrice_      Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n    /// @param markup_          Markup for the message execution (in BWAD)\n    function encodeGasData(\n        Number gasPrice_,\n        Number dataPrice_,\n        Number execBuffer_,\n        Number amortAttCost_,\n        Number etherPrice_,\n        Number markup_\n    ) internal pure returns (GasData) {\n        // Number type wraps uint16, so could safely be casted to uint96\n        // forgefmt: disable-next-item\n        return GasData.wrap(\n            uint96(Number.unwrap(gasPrice_)) \u003c\u003c SHIFT_GAS_PRICE |\n            uint96(Number.unwrap(dataPrice_)) \u003c\u003c SHIFT_DATA_PRICE |\n            uint96(Number.unwrap(execBuffer_)) \u003c\u003c SHIFT_EXEC_BUFFER |\n            uint96(Number.unwrap(amortAttCost_)) \u003c\u003c SHIFT_AMORT_ATT_COST |\n            uint96(Number.unwrap(etherPrice_)) \u003c\u003c SHIFT_ETHER_PRICE |\n            uint96(Number.unwrap(markup_))\n        );\n    }\n\n    /// @notice Wraps padded uint256 value into GasData struct.\n    function wrapGasData(uint256 paddedGasData) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(paddedGasData));\n    }\n\n    /// @notice Returns the gas price, in Wei per gas unit.\n    function gasPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_GAS_PRICE));\n    }\n\n    /// @notice Returns the calldata price, in Wei per byte of content.\n    function dataPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_DATA_PRICE));\n    }\n\n    /// @notice Returns the tx fee safety buffer for message execution, in Wei.\n    function execBuffer(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_EXEC_BUFFER));\n    }\n\n    /// @notice Returns the amortized cost for attestation submission, in Wei.\n    function amortAttCost(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_AMORT_ATT_COST));\n    }\n\n    /// @notice Returns the ratio of Chain's Ether Price / Mainnet Ether Price, in BWAD math.\n    function etherPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_ETHER_PRICE));\n    }\n\n    /// @notice Returns the markup for the message execution, in BWAD math.\n    function markup(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data)));\n    }\n\n    // ════════════════════════════════════════════════ CHAIN DATA ═════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded ChainGas struct with the given fields.\n    /// @param gasData_ Chain's gas data\n    /// @param domain_  Chain's domain\n    function encodeChainGas(GasData gasData_, uint32 domain_) internal pure returns (ChainGas) {\n        // GasData type wraps uint96, so could safely be casted to uint128\n        return ChainGas.wrap(uint128(GasData.unwrap(gasData_)) \u003c\u003c SHIFT_GAS_DATA | uint128(domain_));\n    }\n\n    /// @notice Wraps padded uint256 value into ChainGas struct.\n    function wrapChainGas(uint256 paddedChainGas) internal pure returns (ChainGas) {\n        // Casting to uint128 will truncate the highest bits, which is the behavior we want\n        return ChainGas.wrap(uint128(paddedChainGas));\n    }\n\n    /// @notice Returns the chain's gas data.\n    function gasData(ChainGas data) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(ChainGas.unwrap(data) \u003e\u003e SHIFT_GAS_DATA));\n    }\n\n    /// @notice Returns the chain's domain.\n    function domain(ChainGas data) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(ChainGas.unwrap(data));\n    }\n\n    /// @notice Returns the hash for the list of ChainGas structs.\n    function snapGasHash(ChainGas[] memory snapGas) internal pure returns (bytes32 snapGasHash_) {\n        // Use assembly to calculate the hash of the array without copying it\n        // ChainGas takes a single word of storage, thus ChainGas[] is stored in the following way:\n        // 0x00: length of the array, in words\n        // 0x20: first ChainGas struct\n        // 0x40: second ChainGas struct\n        // And so on...\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Find the location where the array data starts, we add 0x20 to skip the length field\n            let loc := add(snapGas, 0x20)\n            // Load the length of the array (in words).\n            // Shifting left 5 bits is equivalent to multiplying by 32: this converts from words to bytes.\n            let len := shl(5, mload(snapGas))\n            // Calculate the hash of the array\n            snapGasHash_ := keccak256(loc, len)\n        }\n    }\n}\n\n// contracts/libs/stack/Header.sol\n\n/// Header is encoded data with \"general routing information\".\ntype Header is uint136;\n\nusing HeaderLib for Header global;\n\n/// Types of messages supported by Origin-Destination\n/// - Base: message sent by protocol user, contains tips\n/// - Manager: message sent between AgentManager contracts located on different chains, no tips\nenum MessageFlag {\n    Base,\n    Manager\n}\n\nusing HeaderLib for MessageFlag global;\n\n/// Library for formatting _the header part_ of _the messages used by Origin and Destination_.\n/// - Header represents general information for routing a Message for Origin and Destination.\n/// - Header occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n///\n/// # Header stack layout (from highest bits to lowest)\n///\n/// | Position   | Field            | Type   | Bytes | Description                             |\n/// | ---------- | ---------------- | ------ | ----- | --------------------------------------- |\n/// | (017..016] | flag             | uint8  | 1     | Flag specifying the type of message     |\n/// | (016..012] | origin           | uint32 | 4     | Domain where message originated         |\n/// | (012..008] | nonce            | uint32 | 4     | Message nonce on the origin domain      |\n/// | (008..004] | destination      | uint32 | 4     | Domain where message will be executed   |\n/// | (004..000] | optimisticPeriod | uint32 | 4     | Optimistic period that will be enforced |\nlibrary HeaderLib {\n    /// @dev Amount of bits to shift to flag field\n    uint136 private constant SHIFT_FLAG = 16 * 8;\n    /// @dev Amount of bits to shift to origin field\n    uint136 private constant SHIFT_ORIGIN = 12 * 8;\n    /// @dev Amount of bits to shift to nonce field\n    uint136 private constant SHIFT_NONCE = 8 * 8;\n    /// @dev Amount of bits to shift to destination field\n    uint136 private constant SHIFT_DESTINATION = 4 * 8;\n\n    /// @notice Returns an encoded header with provided fields\n    /// @param origin_              Domain of origin chain\n    /// @param nonce_               Message nonce on origin chain\n    /// @param destination_         Domain of destination chain\n    /// @param optimisticPeriod_    Optimistic period for message execution\n    function encodeHeader(\n        MessageFlag flag_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint32 destination_,\n        uint32 optimisticPeriod_\n    ) internal pure returns (Header) {\n        // All casts below are upcasts, so they are safe\n        // forgefmt: disable-next-item\n        return Header.wrap(\n            uint136(uint8(flag_)) \u003c\u003c SHIFT_FLAG |\n            uint136(origin_) \u003c\u003c SHIFT_ORIGIN |\n            uint136(nonce_) \u003c\u003c SHIFT_NONCE |\n            uint136(destination_) \u003c\u003c SHIFT_DESTINATION |\n            uint136(optimisticPeriod_)\n        );\n    }\n\n    /// @notice Checks that the header is a valid encoded header.\n    function isHeader(uint256 paddedHeader) internal pure returns (bool) {\n        // Check that flag is within range\n        return _flag(paddedHeader) \u003c= uint8(type(MessageFlag).max);\n    }\n\n    /// @notice Wraps the padded encoded request into a Header-typed value.\n    /// @dev The \"padded\" header is simply an encoded header casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded headers\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedHeader) internal pure returns (Header) {\n        // Check that flag is within range\n        if (!isHeader(paddedHeader)) revert FlagOutOfRange();\n        // Casting to uint136 will truncate the highest bits, which is the behavior we want\n        return Header.wrap(uint136(paddedHeader));\n    }\n\n    /// @notice Returns header's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Header header) internal pure returns (bytes32 hashedHeader) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store header in scratch space\n            mstore(0, header)\n            // Compute hash of header padded to 32 bytes\n            hashedHeader := keccak256(0, 32)\n        }\n    }\n\n    // ══════════════════════════════════════════════ HEADER SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns header's flag field\n    function flag(Header header) internal pure returns (MessageFlag) {\n        // We check that flag is within range when wrapping the header, so this cast is safe\n        return MessageFlag(_flag(Header.unwrap(header)));\n    }\n\n    /// @notice Returns header's origin field\n    function origin(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_ORIGIN);\n    }\n\n    /// @notice Returns header's nonce field\n    function nonce(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_NONCE);\n    }\n\n    /// @notice Returns header's destination field\n    function destination(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_DESTINATION);\n    }\n\n    /// @notice Returns header's optimistic seconds field\n    function optimisticPeriod(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns header's flag field without casting to MessageFlag\n    function _flag(uint256 paddedHeader) private pure returns (uint8) {\n        // Casting to uint8 will truncate the highest bits, which is the behavior we want\n        return uint8(paddedHeader \u003e\u003e SHIFT_FLAG);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n     * constructor.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall \u0026\u0026 _initialized \u003c 1) || (!AddressUpgradeable.isContract(address(this)) \u0026\u0026 _initialized == 1),\n            \"Initializable: contract is already initialized\"\n        );\n        _initialized = 1;\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: setting the version to 255 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing \u0026\u0026 _initialized \u003c version, \"Initializable: contract is already initialized\");\n        _initialized = version;\n        _initializing = true;\n        _;\n        _initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        require(_initializing, \"Initializable: contract is not initializing\");\n        _;\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized != type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint8) {\n        return _initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _initializing;\n    }\n}\n\n// contracts/interfaces/IAgentManager.sol\n\ninterface IAgentManager {\n    /**\n     * @notice Allows Inbox to open a Dispute between a Guard and a Notary, if they are both not in Dispute already.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Guard or Notary is already in Dispute.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Allows Inbox to slash an agent, if their fraud was proven.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Domain doesn't match the saved agent domain.\n     * @param domain    Domain where the Agent is active\n     * @param agent     Address of the Agent\n     * @param prover    Address that initially provided fraud proof\n     */\n    function slashAgent(uint32 domain, address agent, address prover) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest known root of the Agent Merkle Tree.\n     */\n    function agentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns the number of opened Disputes.\n     * @dev This includes the Disputes that have been resolved already.\n     */\n    function getDisputesAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns information about the dispute with the given index.\n     * @dev Will revert if dispute with given index hasn't been opened yet.\n     * @param index             Dispute index\n     * @return guard            Address of the Guard in the Dispute\n     * @return notary           Address of the Notary in the Dispute\n     * @return slashedAgent     Address of the Agent who was slashed when Dispute was resolved\n     * @return fraudProver      Address who provided fraud proof to resolve the Dispute\n     * @return reportPayload    Raw payload with report data that led to the Dispute\n     * @return reportSignature  Guard signature for the report payload\n     */\n    function getDispute(uint256 index)\n        external\n        view\n        returns (\n            address guard,\n            address notary,\n            address slashedAgent,\n            address fraudProver,\n            bytes memory reportPayload,\n            bytes memory reportSignature\n        );\n\n    /**\n     * @notice Returns the current Dispute status of a given agent. See Structures.sol for details.\n     * @dev Every returned value will be set to zero if agent was not slashed and is not in Dispute.\n     * `rival` and `disputePtr` will be set to zero if the agent was slashed without being in Dispute.\n     * @param agent         Agent address\n     * @return flag         Flag describing the current Dispute status for the agent: None/Pending/Slashed\n     * @return rival        Address of the rival agent in the Dispute\n     * @return fraudProver  Address who provided fraud proof to resolve the Dispute\n     * @return disputePtr   Index of the opened Dispute PLUS ONE. Zero if agent is not in Dispute.\n     */\n    function disputeStatus(address agent)\n        external\n        view\n        returns (DisputeFlag flag, address rival, address fraudProver, uint256 disputePtr);\n}\n\n// contracts/interfaces/IAgentSecured.sol\n\ninterface IAgentSecured {\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * between a Guard and a Notary has been opened.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * has been resolved due to one of the agents being slashed.\n     * \u003e `rivalIndex` will be ZERO, if the slashed agent was not in the Dispute.\n     * @param slashedIndex  Index of the slashed agent in the Agent Merkle Tree\n     * @param rivalIndex    Index of the their Dispute Rival in the Agent Merkle Tree\n     */\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the address of the local AgentManager contract, which is treated as\n     * the \"source of truth\" for agent statuses.\n     */\n    function agentManager() external view returns (address);\n\n    /**\n     * @notice Returns the address of the local Inbox contract, which is treated as\n     * the \"source of truth\" for agent-signed statements.\n     * @dev Inbox passes verified agent statements to `IAgentSecured` contract.\n     */\n    function inbox() external view returns (address);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns (flag, openedAt, resolvedAt) that describes the latest status of\n     * the latest dispute for an agent with a given index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param agentIndex    Agent index in the Agent Merkle Tree\n     * @return              Latest dispute status for the given agent: (flag, openedAt, resolvedAt)\n     */\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory);\n}\n\n// contracts/libs/memory/ByteString.sol\n\n/// @dev CallData is a memory view over the payload to be used for an external call, i.e.\n/// recipient.call(callData). Its length is always (4 + 32 * N) bytes:\n/// - First 4 bytes represent the function selector.\n/// - 32 * N bytes represent N words that function arguments occupy.\ntype CallData is uint256;\n\n/// @dev Attach library functions to CallData\nusing ByteString for CallData global;\n\n/// @dev Signature is a memory view over a \"65 bytes\" array representing a ECDSA signature.\ntype Signature is uint256;\n\n/// @dev Attach library functions to Signature\nusing ByteString for Signature global;\n\nlibrary ByteString {\n    using MemViewLib for bytes;\n\n    /**\n     * @dev non-compact ECDSA signatures are enforced as of OZ 4.7.3\n     *\n     *      Signature payload memory layout\n     * [000 .. 032) r   bytes32 32 bytes\n     * [032 .. 064) s   bytes32 32 bytes\n     * [064 .. 065) v   uint8    1 byte\n     */\n    uint256 internal constant SIGNATURE_LENGTH = 65;\n    uint256 private constant OFFSET_R = 0;\n    uint256 private constant OFFSET_S = 32;\n    uint256 private constant OFFSET_V = 64;\n\n    /**\n     * @dev Calldata memory layout\n     * [000 .. 004) selector    bytes4  4 bytes\n     *      Optional: N function arguments\n     * [004 .. 036) arg1        bytes32 32 bytes\n     *      ..\n     * [AAA .. END) argN        bytes32 32 bytes\n     */\n    uint256 internal constant SELECTOR_LENGTH = 4;\n    uint256 private constant OFFSET_SELECTOR = 0;\n    uint256 private constant OFFSET_ARGUMENTS = SELECTOR_LENGTH;\n\n    // ═════════════════════════════════════════════════ SIGNATURE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the signature payload from the given values.\n     * @dev Using ByteString.formatSignature({r: r, s: s, v: v}) will make sure\n     * that params are given in the right order.\n     */\n    function formatSignature(bytes32 r, bytes32 s, uint8 v) internal pure returns (bytes memory) {\n        return abi.encodePacked(r, s, v);\n    }\n\n    /**\n     * @notice Returns a Signature view over for the given payload.\n     * @dev Will revert if the payload is not a signature.\n     */\n    function castToSignature(bytes memory payload) internal pure returns (Signature) {\n        return castToSignature(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Signature view.\n     * @dev Will revert if the memory view is not over a signature.\n     */\n    function castToSignature(MemView memView) internal pure returns (Signature) {\n        if (!isSignature(memView)) revert UnformattedSignature();\n        return Signature.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a signature\n     */\n    function isSignature(MemView memView) internal pure returns (bool) {\n        return memView.len() == SIGNATURE_LENGTH;\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Signature signature) internal pure returns (MemView) {\n        return MemView.wrap(Signature.unwrap(signature));\n    }\n\n    // ═════════════════════════════════════════════ SIGNATURE SLICING ═════════════════════════════════════════════════\n\n    /// @notice Unpacks signature payload into (r, s, v) parameters.\n    /// @dev Make sure to verify signature length with isSignature() beforehand.\n    function toRSV(Signature signature) internal pure returns (bytes32 r, bytes32 s, uint8 v) {\n        // Get the underlying memory view\n        MemView memView = unwrap(signature);\n        r = memView.index({index_: OFFSET_R, bytes_: 32});\n        s = memView.index({index_: OFFSET_S, bytes_: 32});\n        // Can be safely casted to uint8, since we index a single byte\n        v = uint8(memView.indexUint({index_: OFFSET_V, bytes_: 1}));\n    }\n\n    // ═════════════════════════════════════════════════ CALLDATA ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the calldata with the modified arguments:\n     * the existing arguments are prepended with the arguments from the prefix.\n     * @dev Given:\n     *  - `calldata = abi.encodeWithSelector(foo.selector, d, e);`\n     *  - `prefix = abi.encode(a, b, c);`\n     *  - `a`, `b`, `c` are arguments of static type (i.e. not dynamically sized ones)\n     *      Then:\n     *  - Function will return abi.encodeWithSelector(foo.selector, a, c, c, d, e)\n     *  - Returned calldata will trigger `foo(a, b, c, d, e)` when used for a contract call.\n     * Note: for clarification as to what types are considered static, see\n     * https://docs.soliditylang.org/en/latest/abi-spec.html#formal-specification-of-the-encoding\n     * @param callData  Calldata that needs to be modified\n     * @param prefix    ABI-encoded arguments to use as the first arguments in the new calldata\n     * @return Modified calldata having prefix as the first arguments.\n     */\n    function addPrefix(CallData callData, bytes memory prefix) internal view returns (bytes memory) {\n        // Prefix should occupy a whole amount of words in memory\n        if (!_fullWords(prefix.length)) revert UnformattedCallDataPrefix();\n        MemView[] memory views = new MemView[](3);\n        // Use payload's function selector\n        views[0] = abi.encodePacked(callData.callSelector()).ref();\n        // Use prefix as the first arguments\n        views[1] = prefix.ref();\n        // Use payload's remaining arguments\n        views[2] = callData.arguments();\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a CallData view over for the given payload.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(bytes memory payload) internal pure returns (CallData) {\n        return castToCallData(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a CallData view.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(MemView memView) internal pure returns (CallData) {\n        if (!isCallData(memView)) revert UnformattedCallData();\n        return CallData.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a valid calldata, i.e.\n     * a function selector, followed by arbitrary amount of arguments.\n     */\n    function isCallData(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Calldata should at least have a function selector\n        if (length \u003c SELECTOR_LENGTH) return false;\n        // The remainder of the calldata should be exactly N memory words (N \u003e= 0)\n        return _fullWords(length - SELECTOR_LENGTH);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(CallData callData) internal pure returns (MemView) {\n        return MemView.wrap(CallData.unwrap(callData));\n    }\n\n    /// @notice Returns callData's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(CallData callData) internal pure returns (bytes32) {\n        return callData.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ CALLDATA SLICING ══════════════════════════════════════════════════\n\n    /**\n     * @notice Returns amount of memory words (32 byte chunks) the function arguments\n     * occupy in the calldata.\n     * @dev This might differ from amount of arguments supplied, if any of the arguments\n     * occupies more than one memory slot. It is true, however, that argument part of the payload\n     * occupies exactly N words, even for dynamic types like `bytes`\n     */\n    function argumentWords(CallData callData) internal pure returns (uint256) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        // Equivalent of (length - SELECTOR_LENGTH) / 32\n        return (memView.len() - SELECTOR_LENGTH) \u003e\u003e 5;\n    }\n\n    /// @notice Returns selector for the provided calldata.\n    function callSelector(CallData callData) internal pure returns (bytes4) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return bytes4(memView.index({index_: OFFSET_SELECTOR, bytes_: SELECTOR_LENGTH}));\n    }\n\n    /// @notice Returns abi encoded arguments for the provided calldata.\n    function arguments(CallData callData) internal pure returns (MemView) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return memView.sliceFrom({index_: OFFSET_ARGUMENTS});\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if length is full amount of memory words (32 bytes).\n    function _fullWords(uint256 length) internal pure returns (bool) {\n        // The equivalent of length % 32 == 0\n        return length \u0026 31 == 0;\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n    function __Context_init() internal onlyInitializing {\n    }\n\n    function __Context_init_unchained() internal onlyInitializing {\n    }\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[50] private __gap;\n}\n\n// contracts/libs/merkle/MerkleTree.sol\n\n/// `BaseTree` is a struct representing incremental merkle tree.\n/// - Contains only the current branch.\n/// - The number of inserted leaves is stored externally, and is later supplied for tree operations.\n/// - Has a fixed height of `ORIGIN_TREE_HEIGHT`.\n/// - Can store up to `2 ** ORIGIN_TREE_HEIGHT - 1` leaves.\n/// \u003e Note: the hash function for the tree `H(x, y)` is defined as:\n/// \u003e - `H(0,0) = 0`\n/// \u003e - `H(x,y) = keccak256(x, y), when (x != 0 || y != 0)`\n/// ## Invariant for leafs\n/// - The leftmost empty leaf has `index == count`, where `count` is the amount of the inserted leafs so far.\n/// - Value for any empty leaf or node is bytes32(0).\n/// ## Invariant for current branch\n/// `branch[i]` is always the value of a node on the i-th level.\n/// Levels are numbered from leafs to root: `0 .. ORIGIN_TREE_HEIGHT`.\n/// `branch[i]` stores the value for the node, such that:\n//  - The node is a \"left child\" (e.g. has an even index).\n/// - The node must have two non-empty children.\n/// - Out of all level's \"left child\" nodes with \"non-empty children\",\n/// the one with the biggest index (the rightmost one) is stored as `branch[i]`.\n/// \u003e __`branch` could be used to form a proof of inclusion for the first empty leaf (`index == count`).__\n/// _Here is how:_\n/// - Let's walk along the path from the \"first empty leaf\" to the root.\n/// - i-th bit of the \"first empty leaf\" index (which is equal to `count`) determines if the path's node\n/// for this i-th level is a \"left child\" or a \"right child\".\n/// - i-th bit in `count` is 0 → we are the left child on this level → sibling is the right child\n/// that does not exist yet → `proof[i] = bytes32(0)`.\n/// - i-th bit in `count` is 1 → we are the right child on this level → sibling is the left child\n/// sibling is the rightmost \"left child\" node on the level → `proof[i] = branch[i]`.\n/// \u003e Therefore `proof[i] = (count \u0026 (1 \u003c\u003c i)) == 0 ? bytes32(0) : branch[i])`\nstruct BaseTree {\n    bytes32[ORIGIN_TREE_HEIGHT] branch;\n}\n\nusing MerkleTree for BaseTree global;\n\n/// `HistoricalTree` is an incremental merkle tree keeping track of its historical merkle roots.\n/// \u003e - `roots[N]` is the root of the tree after `N` leafs were inserted\n/// \u003e - `roots[0] == bytes32(0)`\n/// @param tree     Incremental merkle tree\n/// @param roots    Historical merkle roots of the tree\nstruct HistoricalTree {\n    BaseTree tree;\n    bytes32[] roots;\n}\n\nusing MerkleTree for HistoricalTree global;\n\n/// `DynamicTree` is a struct representing a Merkle Tree with `2**AGENT_TREE_HEIGHT` leaves.\n/// - A single operation is available: update value for leaf with an arbitrary index (which might be a non-empty leaf).\n/// - This is done by requesting the proof of inclusion for the old value, which is used to both\n/// verify the old value, and calculate the new root.\n/// \u003e Based on Original idea from [ER forum post](https://ethresear.ch/t/efficient-on-chain-dynamic-merkle-tree/11054).\nstruct DynamicTree {\n    bytes32 root;\n}\n\nusing MerkleTree for DynamicTree global;\n\n/// MerkleTree is work based on Nomad's Merkle.sol, which is used under MIT OR Apache-2.0\n/// [link](https://github.com/nomad-xyz/monorepo/blob/main/packages/contracts-core/contracts/libs/Merkle.sol).\n/// With the following changes:\n/// - Adapted for Solidity 0.8.x.\n/// - Amount of tree leaves stored externally.\n/// - Added thorough documentation.\n/// - `H(0,0) = 0` optimization from [ER forum post](https://ethresear.ch/t/optimizing-sparse-merkle-trees/3751/6).\n/// \u003e Nomad's Merkle.sol is work based on eth2 deposit contract, which is used under CC0-1.0\n///[link](https://github.com/ethereum/deposit_contract/blob/dev/deposit_contract/contracts/validator_registration.v.py).\n/// With the following changes:\n/// \u003e - Implemented in Solidity 0.7.6 (eth2 deposit contract implemented in Vyper).\n/// \u003e - `H() = keccak256()` is used as the hashing function instead of `sha256()`.\nlibrary MerkleTree {\n    /// @dev For root calculation we need at least one empty leaf, thus the minus one in the formula.\n    uint256 internal constant MAX_LEAVES = 2 ** ORIGIN_TREE_HEIGHT - 1;\n\n    // ═════════════════════════════════════════════════ BASE TREE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Inserts `node` into merkle tree\n     * @dev Reverts if tree is full\n     * @param newCount  Amount of inserted leaves in the tree after the insertion (i.e. current + 1)\n     * @param node      Element to insert into tree\n     */\n    function insertBase(BaseTree storage tree, uint256 newCount, bytes32 node) internal {\n        if (newCount \u003e MAX_LEAVES) revert MerkleTreeFull();\n        // We go up the tree following the branch from the empty leaf AFTER the just inserted one.\n        // We stop when we find the first \"right child\" node.\n        // Its sibling is now the rightmost \"left child\" node that has two non-empty children.\n        // Therefore we need to update `tree.branch` value on this level.\n        // One could see that `tree.branch` value on lower and higher levels remain unchanged.\n\n        // Loop invariant: `node` is the current level's value for the branch from JUST INSERTED leaf\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            if ((newCount \u0026 1) == 1) {\n                // Found the first \"right child\" node on the branch from EMPTY leaf\n                // `node` is the value for node on branch from JUST INSERTED leaf\n                // Which in this case is the \"left child\".\n                // We update tree.branch and exit\n                tree.branch[i] = node;\n                return;\n            }\n            // On the branch from EMPTY leaf this is still a \"left child\".\n            // Meaning on branch from JUST INSERTED leaf, `node` is a right child.\n            // We compute value for `node` parent using `tree.branch` invariant:\n            // This is the rightmost \"left child\" node, which would be sibling of `node`.\n            node = MerkleMath.getParent(tree.branch[i], node);\n            // Get the parent index, and go to the next tree level\n            newCount \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n        // As the loop should always end prematurely with the `return` statement,\n        // this code should be unreachable. We assert `false` just to be safe.\n        assert(false);\n    }\n\n    /**\n     * @notice Calculates and returns current root of the merkle tree.\n     * @param count     Current amount of inserted leaves in the tree\n     * @return current  Calculated root of `tree`\n     */\n    function rootBase(BaseTree storage tree, uint256 count) internal view returns (bytes32 current) {\n        // To calculate the root we follow the branch of first EMPTY leaf (index == count)\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            // Check if we are the left or the right child on the current level\n            if ((count \u0026 1) == 1) {\n                // We are the right child. Our sibling is the \"rightmost\" \"left-child\" node\n                // that has two non-empty children → sibling is `tree.branch[i]`\n                current = MerkleMath.getParent(tree.branch[i], current);\n            } else {\n                // We are the left child. Our sibling does not exist yet → sibling is EMPTY\n                current = MerkleMath.getParent(current, bytes32(0));\n            }\n            // Get the parent index, and go to the next tree level\n            count \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    // ══════════════════════════════════════════════ HISTORICAL TREE ══════════════════════════════════════════════════\n\n    /// @notice Initializes the historical roots for the tree by inserting an empty root.\n    // solhint-disable-next-line ordering\n    function initializeRoots(HistoricalTree storage tree) internal returns (bytes32 savedRoot) {\n        // This should only be called once, when the contract is initialized\n        assert(tree.roots.length == 0);\n        // Save root for empty merkle tree: bytes32(0)\n        tree.roots.push(savedRoot);\n    }\n\n    /// @notice Inserts a new leaf into the merkle tree.\n    /// @dev Reverts if tree is full.\n    /// @param node         Element to insert into tree\n    /// @return newRoot     Merkle root after the leaf was inserted\n    function insert(HistoricalTree storage tree, bytes32 node) internal returns (bytes32 newRoot) {\n        // Tree count after the new leaf will be inserted (we store roots[0] as root of empty tree)\n        uint256 newCount = tree.roots.length;\n        tree.tree.insertBase(newCount, node);\n        // Save the new root\n        newRoot = tree.tree.rootBase(newCount);\n        tree.roots.push(newRoot);\n    }\n\n    /// @notice Returns the historical root of the merkle tree.\n    /// @dev Reverts if not enough leafs have been inserted.\n    /// @param count            Amount of leafs in the tree at some point of time\n    /// @return historicalRoot  Merkle root after `count` leafs were inserted\n    function root(HistoricalTree storage tree, uint256 count) internal view returns (bytes32 historicalRoot) {\n        if (count \u003e= tree.roots.length) revert NotEnoughLeafs();\n        return tree.roots[count];\n    }\n\n    // ═══════════════════════════════════════════════ DYNAMIC TREE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Updates the value for the leaf with the given index in the Dynamic Merkle Tree.\n     * @dev Will revert if incorrect proof of inclusion for old value is supplied.\n     * @param tree          Dynamic merkle tree\n     * @param index         Index of the leaf to update\n     * @param oldValue      Previous value of the leaf\n     * @param branch        Proof of inclusion of previous value into the tree\n     * @param newValue      New leaf value to assign\n     * @return newRoot      New value for the Merkle Root after the leaf is updated\n     */\n    function update(\n        DynamicTree storage tree,\n        uint256 index,\n        bytes32 oldValue,\n        bytes32[] memory branch,\n        bytes32 newValue\n    ) internal returns (bytes32 newRoot) {\n        // Check that the old value + proof result in a correct root\n        if (MerkleMath.proofRoot(index, oldValue, branch, AGENT_TREE_HEIGHT) != tree.root) {\n            revert LeafNotProven();\n        }\n        // New root is new value + the same proof (values for sibling nodes are not updated)\n        newRoot = MerkleMath.proofRoot(index, newValue, branch, AGENT_TREE_HEIGHT);\n        // Write the new root\n        tree.root = newRoot;\n    }\n}\n\n// contracts/libs/stack/Tips.sol\n\n/// Tips is encoded data with \"tips paid for sending a base message\".\n/// Note: even though uint256 is also an underlying type for MemView, Tips is stored ON STACK.\ntype Tips is uint256;\n\nusing TipsLib for Tips global;\n\n/// # Tips\n/// Library for formatting _the tips part_ of _the base messages_.\n///\n/// ## How the tips are awarded\n/// Tips are paid for sending a base message, and are split across all the agents that\n/// made the message execution on destination chain possible.\n/// ### Summit tips\n/// Split between:\n///     - Guard posting a snapshot with state ST_G for the origin chain.\n///     - Notary posting a snapshot SN_N using ST_G. This creates attestation A.\n///     - Notary posting a message receipt after it is executed on destination chain.\n/// ### Attestation tips\n/// Paid to:\n///     - Notary posting attestation A to destination chain.\n/// ### Execution tips\n/// Paid to:\n///     - First executor performing a valid execution attempt (correct proofs, optimistic period over),\n///      using attestation A to prove message inclusion on origin chain, whether the recipient reverted or not.\n/// ### Delivery tips.\n/// Paid to:\n///     - Executor who successfully executed the message on destination chain.\n///\n/// ## Tips encoding\n/// - Tips occupy a single storage word, and thus are stored on stack instead of being stored in memory.\n/// - The actual tip values should be determined by multiplying stored values by divided by TIPS_MULTIPLIER=2**32.\n/// - Tips are packed into a single word of storage, while allowing real values up to ~8*10**28 for every tip category.\n/// \u003e The only downside is that the \"real tip values\" are now multiplies of ~4*10**9, which should be fine even for\n/// the chains with the most expensive gas currency.\n/// # Tips stack layout (from highest bits to lowest)\n///\n/// | Position   | Field          | Type   | Bytes | Description                                                |\n/// | ---------- | -------------- | ------ | ----- | ---------------------------------------------------------- |\n/// | (032..024] | summitTip      | uint64 | 8     | Tip for agents interacting with Summit contract            |\n/// | (024..016] | attestationTip | uint64 | 8     | Tip for Notary posting attestation to Destination contract |\n/// | (016..008] | executionTip   | uint64 | 8     | Tip for valid execution attempt on destination chain       |\n/// | (008..000] | deliveryTip    | uint64 | 8     | Tip for successful message delivery on destination chain   |\n\nlibrary TipsLib {\n    using SafeCast for uint256;\n\n    /// @dev Amount of bits to shift to summitTip field\n    uint256 private constant SHIFT_SUMMIT_TIP = 24 * 8;\n    /// @dev Amount of bits to shift to attestationTip field\n    uint256 private constant SHIFT_ATTESTATION_TIP = 16 * 8;\n    /// @dev Amount of bits to shift to executionTip field\n    uint256 private constant SHIFT_EXECUTION_TIP = 8 * 8;\n\n    // ═══════════════════════════════════════════════════ TIPS ════════════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips with the given fields\n    /// @param summitTip_        Tip for agents interacting with Summit contract, divided by TIPS_MULTIPLIER\n    /// @param attestationTip_   Tip for Notary posting attestation to Destination contract, divided by TIPS_MULTIPLIER\n    /// @param executionTip_     Tip for valid execution attempt on destination chain, divided by TIPS_MULTIPLIER\n    /// @param deliveryTip_      Tip for successful message delivery on destination chain, divided by TIPS_MULTIPLIER\n    function encodeTips(uint64 summitTip_, uint64 attestationTip_, uint64 executionTip_, uint64 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // forgefmt: disable-next-item\n        return Tips.wrap(\n            uint256(summitTip_) \u003c\u003c SHIFT_SUMMIT_TIP |\n            uint256(attestationTip_) \u003c\u003c SHIFT_ATTESTATION_TIP |\n            uint256(executionTip_) \u003c\u003c SHIFT_EXECUTION_TIP |\n            uint256(deliveryTip_)\n        );\n    }\n\n    /// @notice Convenience function to encode tips with uint256 values.\n    function encodeTips256(uint256 summitTip_, uint256 attestationTip_, uint256 executionTip_, uint256 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // In practice, the tips amounts are not supposed to be higher than 2**96, and with 32 bits of granularity\n        // using uint64 is enough to store the values. However, we still check for overflow just in case.\n        // TODO: consider using Number type to store the tips values.\n        return encodeTips({\n            summitTip_: (summitTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            attestationTip_: (attestationTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            executionTip_: (executionTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            deliveryTip_: (deliveryTip_ \u003e\u003e TIPS_GRANULARITY).toUint64()\n        });\n    }\n\n    /// @notice Wraps the padded encoded tips into a Tips-typed value.\n    /// @dev There is no actual padding here, as the underlying type is already uint256,\n    /// but we include this function for consistency and to be future-proof, if tips will eventually use anything\n    /// smaller than uint256.\n    function wrapPadded(uint256 paddedTips) internal pure returns (Tips) {\n        return Tips.wrap(paddedTips);\n    }\n\n    /**\n     * @notice Returns a formatted Tips payload specifying empty tips.\n     * @return Formatted tips\n     */\n    function emptyTips() internal pure returns (Tips) {\n        return Tips.wrap(0);\n    }\n\n    /// @notice Returns tips's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Tips tips) internal pure returns (bytes32 hashedTips) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store tips in scratch space\n            mstore(0, tips)\n            // Compute hash of tips padded to 32 bytes\n            hashedTips := keccak256(0, 32)\n        }\n    }\n\n    // ═══════════════════════════════════════════════ TIPS SLICING ════════════════════════════════════════════════════\n\n    /// @notice Returns summitTip field\n    function summitTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_SUMMIT_TIP);\n    }\n\n    /// @notice Returns attestationTip field\n    function attestationTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_ATTESTATION_TIP);\n    }\n\n    /// @notice Returns executionTip field\n    function executionTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_EXECUTION_TIP);\n    }\n\n    /// @notice Returns deliveryTip field\n    function deliveryTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips));\n    }\n\n    // ════════════════════════════════════════════════ TIPS VALUE ═════════════════════════════════════════════════════\n\n    /// @notice Returns total value of the tips payload.\n    /// This is the sum of the encoded values, scaled up by TIPS_MULTIPLIER\n    function value(Tips tips) internal pure returns (uint256 value_) {\n        value_ = uint256(tips.summitTip()) + tips.attestationTip() + tips.executionTip() + tips.deliveryTip();\n        value_ \u003c\u003c= TIPS_GRANULARITY;\n    }\n\n    /// @notice Increases the delivery tip to match the new value.\n    function matchValue(Tips tips, uint256 newValue) internal pure returns (Tips newTips) {\n        uint256 oldValue = tips.value();\n        if (newValue \u003c oldValue) revert TipsValueTooLow();\n        // We want to increase the delivery tip, while keeping the other tips the same\n        unchecked {\n            uint256 delta = (newValue - oldValue) \u003e\u003e TIPS_GRANULARITY;\n            // `delta` fits into uint224, as TIPS_GRANULARITY is 32, so this never overflows uint256.\n            // In practice, this will never overflow uint64 as well, but we still check it just in case.\n            if (delta + tips.deliveryTip() \u003e type(uint64).max) revert TipsOverflow();\n            // Delivery tips occupy lowest 8 bytes, so we can just add delta to the tips value\n            // to effectively increase the delivery tip (knowing that delta fits into uint64).\n            newTips = Tips.wrap(Tips.unwrap(tips) + delta);\n        }\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    function __Ownable_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable_init_unchained() internal onlyInitializing {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n    function __Ownable2Step_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable2Step_init_unchained() internal onlyInitializing {\n    }\n    address private _pendingOwner;\n\n    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Returns the address of the pending owner.\n     */\n    function pendingOwner() public view virtual returns (address) {\n        return _pendingOwner;\n    }\n\n    /**\n     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual override onlyOwner {\n        _pendingOwner = newOwner;\n        emit OwnershipTransferStarted(owner(), newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual override {\n        delete _pendingOwner;\n        super._transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev The new owner accepts the ownership transfer.\n     */\n    function acceptOwnership() public virtual {\n        address sender = _msgSender();\n        require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n        _transferOwnership(sender);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// contracts/libs/memory/State.sol\n\n/// State is a memory view over a formatted state payload.\ntype State is uint256;\n\nusing StateLib for State global;\n\n/// # State\n/// State structure represents the state of Origin contract at some point of time.\n/// - State is structured in a way to track the updates of the Origin Merkle Tree.\n/// - State includes root of the Origin Merkle Tree, origin domain and some additional metadata.\n/// ## Origin Merkle Tree\n/// Hash of every sent message is inserted in the Origin Merkle Tree, which changes\n/// the value of Origin Merkle Root (which is the root for the mentioned tree).\n/// - Origin has a single Merkle Tree for all messages, regardless of their destination domain.\n/// - This leads to Origin state being updated if and only if a message was sent in a block.\n/// - Origin contract is a \"source of truth\" for states: a state is considered \"valid\" in its Origin,\n/// if it matches the state of the Origin contract after the N-th (nonce) message was sent.\n///\n/// # Memory layout of State fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                    |\n/// | ---------- | ----------- | ------- | ----- | ------------------------------ |\n/// | [000..032) | root        | bytes32 | 32    | Root of the Origin Merkle Tree |\n/// | [032..036) | origin      | uint32  | 4     | Domain where Origin is located |\n/// | [036..040) | nonce       | uint32  | 4     | Amount of sent messages        |\n/// | [040..045) | blockNumber | uint40  | 5     | Block of last sent message     |\n/// | [045..050) | timestamp   | uint40  | 5     | Time of last sent message      |\n/// | [050..062) | gasData     | uint96  | 12    | Gas data for the chain         |\n///\n/// @dev State could be used to form a Snapshot to be signed by a Guard or a Notary.\nlibrary StateLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_ROOT = 0;\n    uint256 private constant OFFSET_ORIGIN = 32;\n    uint256 private constant OFFSET_NONCE = 36;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 40;\n    uint256 private constant OFFSET_TIMESTAMP = 45;\n    uint256 private constant OFFSET_GAS_DATA = 50;\n\n    // ═══════════════════════════════════════════════════ STATE ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted State payload with provided fields\n     * @param root_         New merkle root\n     * @param origin_       Domain of Origin's chain\n     * @param nonce_        Nonce of the merkle root\n     * @param blockNumber_  Block number when root was saved in Origin\n     * @param timestamp_    Block timestamp when root was saved in Origin\n     * @param gasData_      Gas data for the chain\n     * @return Formatted state\n     */\n    function formatState(\n        bytes32 root_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_,\n        GasData gasData_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(root_, origin_, nonce_, blockNumber_, timestamp_, gasData_);\n    }\n\n    /**\n     * @notice Returns a State view over the given payload.\n     * @dev Will revert if the payload is not a state.\n     */\n    function castToState(bytes memory payload) internal pure returns (State) {\n        return castToState(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a State view.\n     * @dev Will revert if the memory view is not over a state.\n     */\n    function castToState(MemView memView) internal pure returns (State) {\n        if (!isState(memView)) revert UnformattedState();\n        return State.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted State.\n    function isState(MemView memView) internal pure returns (bool) {\n        return memView.len() == STATE_LENGTH;\n    }\n\n    /// @notice Returns the hash of a State, that could be later signed by a Guard to signal\n    /// that the state is invalid.\n    function hashInvalid(State state) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(stateInvalidSalt, keccak(state))\n        return state.unwrap().keccakSalted(STATE_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(State state) internal pure returns (MemView) {\n        return MemView.wrap(State.unwrap(state));\n    }\n\n    /// @notice Compares two State structures.\n    function equals(State a, State b) internal pure returns (bool) {\n        // Length of a State payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═══════════════════════════════════════════════ STATE HASHING ═══════════════════════════════════════════════════\n\n    /// @notice Returns the hash of the State.\n    /// @dev We are using the Merkle Root of a tree with two leafs (see below) as state hash.\n    function leaf(State state) internal pure returns (bytes32) {\n        (bytes32 leftLeaf_, bytes32 rightLeaf_) = state.subLeafs();\n        // Final hash is the parent of these leafs\n        return keccak256(bytes.concat(leftLeaf_, rightLeaf_));\n    }\n\n    /// @notice Returns \"sub-leafs\" of the State. Hash of these \"sub leafs\" is going to be used\n    /// as a \"state leaf\" in the \"Snapshot Merkle Tree\".\n    /// This enables proving that leftLeaf = (root, origin) was a part of the \"Snapshot Merkle Tree\",\n    /// by combining `rightLeaf` with the remainder of the \"Snapshot Merkle Proof\".\n    function subLeafs(State state) internal pure returns (bytes32 leftLeaf_, bytes32 rightLeaf_) {\n        MemView memView = state.unwrap();\n        // Left leaf is (root, origin)\n        leftLeaf_ = memView.prefix({len_: OFFSET_NONCE}).keccak();\n        // Right leaf is (metadata), or (nonce, blockNumber, timestamp)\n        rightLeaf_ = memView.sliceFrom({index_: OFFSET_NONCE}).keccak();\n    }\n\n    /// @notice Returns the left \"sub-leaf\" of the State.\n    function leftLeaf(bytes32 root_, uint32 origin_) internal pure returns (bytes32) {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(root_, origin_));\n    }\n\n    /// @notice Returns the right \"sub-leaf\" of the State.\n    function rightLeaf(uint32 nonce_, uint40 blockNumber_, uint40 timestamp_, GasData gasData_)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(nonce_, blockNumber_, timestamp_, gasData_));\n    }\n\n    // ═══════════════════════════════════════════════ STATE SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns a historical Merkle root from the Origin contract.\n    function root(State state) internal pure returns (bytes32) {\n        return state.unwrap().index({index_: OFFSET_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns domain of chain where the Origin contract is deployed.\n    function origin(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns nonce of Origin contract at the time, when `root` was the Merkle root.\n    function nonce(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when `root` was saved in Origin.\n    function blockNumber(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when `root` was saved in Origin.\n    /// @dev This is the timestamp according to the origin chain.\n    function timestamp(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n\n    /// @notice Returns gas data for the chain.\n    function gasData(State state) internal pure returns (GasData) {\n        return GasDataLib.wrapGasData(state.unwrap().indexUint({index_: OFFSET_GAS_DATA, bytes_: GAS_DATA_LENGTH}));\n    }\n}\n\n// contracts/libs/memory/BaseMessage.sol\n\n/// BaseMessage is a memory view over the base message supported by Origin-Destination\ntype BaseMessage is uint256;\n\nusing BaseMessageLib for BaseMessage global;\n\n/// BaseMessage structure represents a base message sent via the Origin-Destination contracts.\n/// - It only contains data relevant to the base message, the rest of data is encoded in the message header.\n/// - `sender` and `recipient` for EVM chains are EVM addresses casted to bytes32, while preserving left-alignment.\n/// - `tips` and `request` parameters are specified by a message sender\n/// \u003e Origin will calculate minimum tips for given request and content length, and will reject messages with tips\n/// lower than that.\n///\n/// # Memory layout of BaseMessage fields\n///\n/// | Position   | Field     | Type    | Bytes | Description                            |\n/// | ---------- | --------- | ------- | ----- | -------------------------------------- |\n/// | [000..032) | tips      | uint256 | 32    | Encoded tips paid on origin chain      |\n/// | [032..064) | sender    | bytes32 | 32    | Sender address on origin chain         |\n/// | [064..096) | recipient | bytes32 | 32    | Recipient address on destination chain |\n/// | [096..116) | request   | uint160 | 20    | Encoded request for message execution  |\n/// | [104..AAA) | content   | bytes   | ??    | Content to be passed to recipient      |\nlibrary BaseMessageLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_TIPS = 0;\n    uint256 private constant OFFSET_SENDER = 32;\n    uint256 private constant OFFSET_RECIPIENT = 64;\n    uint256 private constant OFFSET_REQUEST = OFFSET_RECIPIENT + TIPS_LENGTH;\n    uint256 private constant OFFSET_CONTENT = OFFSET_REQUEST + REQUEST_LENGTH;\n\n    // ═══════════════════════════════════════════════ BASE MESSAGE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted BaseMessage payload with provided fields.\n     * @param tips_         Encoded tips information\n     * @param sender_       Sender address on origin chain\n     * @param recipient_    Recipient address on destination chain\n     * @param request_      Encoded request for message execution\n     * @param content_      Raw content to be passed to recipient on destination chain\n     * @return Formatted base message\n     */\n    function formatBaseMessage(Tips tips_, bytes32 sender_, bytes32 recipient_, Request request_, bytes memory content_)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return abi.encodePacked(tips_, sender_, recipient_, request_, content_);\n    }\n\n    /**\n     * @notice Returns a BaseMessage view over the given payload.\n     * @dev Will revert if the payload is not a base message.\n     */\n    function castToBaseMessage(bytes memory payload) internal pure returns (BaseMessage) {\n        return castToBaseMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a BaseMessage view.\n     * @dev Will revert if the memory view is not over a base message payload.\n     */\n    function castToBaseMessage(MemView memView) internal pure returns (BaseMessage) {\n        if (!isBaseMessage(memView)) revert UnformattedBaseMessage();\n        return BaseMessage.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted BaseMessage.\n    function isBaseMessage(MemView memView) internal pure returns (bool) {\n        // Check if sender, recipient, tips fields exist\n        return (memView.len() \u003e= OFFSET_CONTENT);\n        // Content could be empty, so we don't check that\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(BaseMessage baseMessage) internal pure returns (MemView) {\n        return MemView.wrap(BaseMessage.unwrap(baseMessage));\n    }\n\n    /// @notice Returns baseMessage's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        // We hash \"tips\" and \"everything but tips\" to make tips proofs easier to verify\n        return MerkleMath.getParent(baseMessage.tips().leaf(), baseMessage.bodyLeaf());\n    }\n\n    /// @notice Returns hash for the \"everything but tips\" part of the base message.\n    function bodyLeaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_SENDER}).keccak();\n    }\n\n    // ═══════════════════════════════════════════ BASE MESSAGE SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips paid on origin chain.\n    function tips(BaseMessage baseMessage) internal pure returns (Tips) {\n        return TipsLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_TIPS, bytes_: TIPS_LENGTH})));\n    }\n\n    /// @notice Returns sender address on origin chain.\n    function sender(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_SENDER, bytes_: 32});\n    }\n\n    /// @notice Returns recipient address on destination chain.\n    function recipient(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_RECIPIENT, bytes_: 32});\n    }\n\n    /// @notice Returns an encoded request for message execution on destination chain.\n    function request(BaseMessage baseMessage) internal pure returns (Request) {\n        return RequestLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_REQUEST, bytes_: REQUEST_LENGTH})));\n    }\n\n    /// @notice Returns an untyped memory view over the content to be passed to recipient.\n    function content(BaseMessage baseMessage) internal pure returns (MemView) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_CONTENT});\n    }\n}\n\n// contracts/base/MessagingBase.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for all messaging contracts.\n * - Provides context on the local chain's domain.\n * - Provides ownership functionality.\n * - Will be providing pausing functionality when it is implemented.\n */\nabstract contract MessagingBase is MultiCallable, Versioned, Ownable2StepUpgradeable {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @notice Domain of the local chain, set once upon contract creation\n    uint32 public immutable localDomain;\n    // @notice Domain of the Synapse chain, set once upon contract creation\n    uint32 public immutable synapseDomain;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev gap for upgrade safety\n    uint256[50] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    constructor(string memory version_, uint32 synapseDomain_) Versioned(version_) {\n        localDomain = ChainContext.chainId();\n        synapseDomain = synapseDomain_;\n    }\n\n    // TODO: Implement pausing\n\n    /**\n     * @dev Should be impossible to renounce ownership;\n     * we override OpenZeppelin OwnableUpgradeable's\n     * implementation of renounceOwnership to make it a no-op\n     */\n    function renounceOwnership() public override onlyOwner {} //solhint-disable-line no-empty-blocks\n}\n\n// contracts/libs/memory/Message.sol\n\n/// Message is a memory over over a formatted message payload.\ntype Message is uint256;\n\nusing MessageLib for Message global;\n\n/// Library for formatting the various messages supported by Origin and Destination.\n///\n/// # Message memory layout\n///\n/// | Position   | Field  | Type    | Bytes | Description                                             |\n/// | ---------- | ------ | ------- | ----- | ------------------------------------------------------- |\n/// | [000..017) | header | uint136 | 17    | Encoded general routing information for the message     |\n/// | [017..AAA) | body   | bytes   | ??    | Formatted payload (according to flag) with message body |\nlibrary MessageLib {\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MemViewLib for bytes;\n    using HeaderLib for MemView;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_HEADER = 0;\n    uint256 private constant OFFSET_BODY = OFFSET_HEADER + HEADER_LENGTH;\n\n    // ══════════════════════════════════════════════════ MESSAGE ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns formatted message with provided fields.\n     * @param header_   Encoded general routing information for the message\n     * @param body_     Formatted payload (according to flag) with message body\n     * @return Formatted message\n     */\n    function formatMessage(Header header_, bytes memory body_) internal pure returns (bytes memory) {\n        return abi.encodePacked(header_, body_);\n    }\n\n    /**\n     * @notice Returns a Message view over for the given payload.\n     * @dev Will revert if the payload is not a message payload.\n     */\n    function castToMessage(bytes memory payload) internal pure returns (Message) {\n        return castToMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Message view.\n     * @dev Will revert if the memory view is not over a message payload.\n     */\n    function castToMessage(MemView memView) internal pure returns (Message) {\n        if (!isMessage(memView)) revert UnformattedMessage();\n        return Message.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Message.\n     */\n    function isMessage(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Check if headers exist in the payload\n        if (length \u003c OFFSET_BODY) return false;\n        // Check that Header is valid\n        uint256 paddedHeader = _header(memView);\n        if (!HeaderLib.isHeader(paddedHeader)) return false;\n        // Check that body is formatted according to the flag\n        // Only Base/Manager message flags exist\n        if (HeaderLib.wrapPadded(paddedHeader).flag() == MessageFlag.Base) {\n            // Check if body is a formatted base message\n            return _body(memView).isBaseMessage();\n        } else {\n            // Check if body is a formatted calldata for AgentManager call\n            return _body(memView).isCallData();\n        }\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Message message) internal pure returns (MemView) {\n        return MemView.wrap(Message.unwrap(message));\n    }\n\n    /// @notice Returns message's hash: a leaf to be inserted in the Merkle tree.\n    function leaf(Message message) internal pure returns (bytes32) {\n        // We hash header and body separately to make message proofs easier to verify\n        Header header_ = message.header();\n        // Only Base/Manager message flags exist\n        if (header_.flag() == MessageFlag.Base) {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToBaseMessage().leaf());\n        } else {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToCallData().leaf());\n        }\n    }\n\n    // ══════════════════════════════════════════════ MESSAGE SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns message's encoded header field.\n    function header(Message message) internal pure returns (Header) {\n        return HeaderLib.wrapPadded((message.unwrap().indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH})));\n    }\n\n    /// @notice Returns message's body field as an untyped memory view.\n    function body(Message message) internal pure returns (MemView) {\n        MemView memView = message.unwrap();\n        return _body(memView);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns message's padded header without checking that it is a valid header.\n    function _header(MemView memView) private pure returns (uint256) {\n        return memView.indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH});\n    }\n\n    /// @dev Returns an untyped memory view over the body field without checking\n    /// if the whole payload or the body are properly formatted.\n    function _body(MemView memView) private pure returns (MemView) {\n        return memView.sliceFrom({index_: OFFSET_BODY});\n    }\n}\n\n// contracts/base/AgentSecured.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for messaging contracts that are secured by the agent manager.\n * `AgentSecured` relies on `AgentManager` to provide the following functionality:\n * - Keep track of agents and their statuses.\n * - Pass agent-signed statements that were verified by the agent manager.\n * - These statements are considered valid indefinitely, unless the agent is disputed.\n * - Disputes are opened and resolved by the agent manager.\n * \u003e `AgentSecured` implementation should never use statements signed by agents that are disputed.\n */\nabstract contract AgentSecured is MessagingBase, IAgentSecured {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    address public immutable agentManager;\n\n    /// @inheritdoc IAgentSecured\n    address public immutable inbox;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    // (agent index =\u003e their dispute status: flag, openedAt, resolvedAt)\n    mapping(uint32 =\u003e DisputeStatus) internal _disputes;\n\n    /// @dev gap for upgrade safety\n    uint256[49] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    modifier onlyAgentManager() {\n        if (msg.sender != agentManager) revert CallerNotAgentManager();\n        _;\n    }\n\n    modifier onlyInbox() {\n        if (msg.sender != inbox) revert CallerNotInbox();\n        _;\n    }\n\n    constructor(string memory version_, uint32 synapseDomain_, address agentManager_, address inbox_)\n        MessagingBase(version_, synapseDomain_)\n    {\n        agentManager = agentManager_;\n        inbox = inbox_;\n    }\n\n    // ════════════════════════════════════════════ ONLY AGENT MANAGER ═════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external onlyAgentManager {\n        uint40 openedAt = ChainContext.blockTimestamp();\n        DisputeStatus memory status = DisputeStatus({flag: DisputeFlag.Pending, openedAt: openedAt, resolvedAt: 0});\n        _disputes[guardIndex] = status;\n        _disputes[notaryIndex] = status;\n    }\n\n    /// @inheritdoc IAgentSecured\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external onlyAgentManager {\n        // Update the dispute status of the slashed agent first.\n        uint40 resolvedAt = ChainContext.blockTimestamp();\n        _disputes[slashedIndex].flag = DisputeFlag.Slashed;\n        _disputes[slashedIndex].resolvedAt = resolvedAt;\n        // Mark the rival agent as not disputed, if there was an ongoing dispute.\n        if (rivalIndex != 0) {\n            _disputes[rivalIndex].flag = DisputeFlag.None;\n            _disputes[rivalIndex].resolvedAt = resolvedAt;\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function agentStatus(address agent) external view returns (AgentStatus memory) {\n        return _agentStatus(agent);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status) {\n        return _getAgent(index);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory) {\n        return _disputes[agentIndex];\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns status of the given agent: (flag, domain, index).\n    function _agentStatus(address agent) internal view returns (AgentStatus memory) {\n        return IAgentManager(agentManager).agentStatus(agent);\n    }\n\n    /// @dev Returns agent and their status for a given agent index. Returns zero values for non existing indexes.\n    function _getAgent(uint256 index) internal view returns (address agent, AgentStatus memory status) {\n        return IAgentManager(agentManager).getAgent(index);\n    }\n\n    /// @dev Checks if a Dispute exists for the given Notary. This function returns true, if\n    /// Notary is in ongoing Dispute, or if Dispute was resolved not in Notary's favor.\n    /// In both cases we can't trust Notary's data.\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeExists(uint32 notaryIndex) internal view returns (bool) {\n        return _disputes[notaryIndex].flag != DisputeFlag.None;\n    }\n\n    /// @dev Checks if a Notary recently won a Dispute and is still in the \"post-dispute\" timeout period.\n    /// In this period we still can't trust Notary's data, though we can optimistically assume that\n    /// that the data will be correct after the timeout (assuming no new Disputes are opened).\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeTimeout(uint32 notaryIndex) internal view returns (bool) {\n        DisputeStatus memory status = _disputes[notaryIndex];\n        // Exit early if Notary is in ongoing Dispute / slashed.\n        if (status.flag != DisputeFlag.None) return false;\n        // Check if Notary has been in any Dispute at all.\n        if (status.openedAt == 0) return false;\n        // Otherwise check if the Dispute timeout is still active.\n        return block.timestamp \u003c status.resolvedAt + DISPUTE_TIMEOUT_NOTARY;\n    }\n}\n\n// contracts/hubs/StateHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StateHub` is a parent contract for `Origin`. It is responsible for the following:\n/// - Keeping track of the historical Origin Merkle Tree containing all the message hashes.\n/// - Keeping track of the historical Origin States, as well as verifying their validity.\nabstract contract StateHub is AgentSecured, StateHubEvents, IStateHub {\n    using SafeCast for uint256;\n    using StateLib for bytes;\n\n    struct OriginState {\n        uint40 blockNumber;\n        uint40 timestamp;\n        GasData gasData;\n    }\n    // Bits left for tight packing: 80\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Historical Merkle Tree\n    /// Note: Takes two storage slots\n    HistoricalTree private _tree;\n\n    /// @dev All historical contract States\n    OriginState[] private _originStates;\n\n    /// @dev gap for upgrade safety\n    uint256[47] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IStateHub\n    function isValidState(bytes memory statePayload) external view returns (bool isValid) {\n        // This will revert if payload is not a formatted state\n        State state = statePayload.castToState();\n        return _isValidState(state);\n    }\n\n    /// @inheritdoc IStateHub\n    function statesAmount() external view returns (uint256) {\n        return _originStates.length;\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestLatestState() external view returns (bytes memory stateData) {\n        // This never underflows, assuming the contract was initialized\n        return suggestState(_nextNonce() - 1);\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestState(uint32 nonce) public view returns (bytes memory stateData) {\n        // This will revert if nonce is out of range\n        bytes32 root = _tree.root(nonce);\n        return _formatOriginState(_originStates[nonce], root, localDomain, nonce);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Initializes the saved states list by inserting a state for an empty Merkle Tree.\n    function _initializeStates() internal {\n        // This should only be called once, when the contract is initialized\n        // This will revert if _tree.roots is non-empty\n        bytes32 savedRoot = _tree.initializeRoots();\n        // Save root for empty merkle _tree with block number and timestamp of initialization\n        _saveState(savedRoot, _toOriginState());\n    }\n\n    /// @dev Inserts leaf into the Merkle Tree and saves the updated origin State.\n    function _insertAndSave(bytes32 leaf) internal {\n        bytes32 newRoot = _tree.insert(leaf);\n        _saveState(newRoot, _toOriginState());\n    }\n\n    /// @dev Saves an updated state of the Origin contract\n    function _saveState(bytes32 root, OriginState memory state) internal {\n        uint32 nonce = _nextNonce();\n        _originStates.push(state);\n        // Emit event with raw state data\n        emit StateSaved(_formatOriginState(state, root, localDomain, nonce));\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns nonce of the next sent message: the amount of saved States so far.\n    /// This always equals to \"total amount of sent messages\" plus 1.\n    function _nextNonce() internal view returns (uint32) {\n        // TODO: consider using more than 32 bits for origin nonces\n        return _originStates.length.toUint32();\n    }\n\n    /// @dev Checks if a state is valid, i.e. if it matches the historical one.\n    /// Reverts, if state refers to another Origin contract.\n    function _isValidState(State state) internal view returns (bool) {\n        // Check if state refers to this contract\n        if (state.origin() != localDomain) revert IncorrectOriginDomain();\n        // Check if nonce exists\n        uint32 nonce = state.nonce();\n        if (nonce \u003e= _originStates.length) return false;\n        // Check if state root matches the historical one\n        if (state.root() != _tree.root(nonce)) return false;\n        // Check if state metadata matches the historical one\n        return _areEqual(state, _originStates[nonce]);\n    }\n\n    // ═════════════════════════════════════════════ STRUCT FORMATTING ═════════════════════════════════════════════════\n\n    /// @dev Returns a formatted payload for a stored OriginState.\n    function _formatOriginState(OriginState memory originState, bytes32 root, uint32 origin, uint32 nonce)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return StateLib.formatState({\n            root_: root,\n            origin_: origin,\n            nonce_: nonce,\n            blockNumber_: originState.blockNumber,\n            timestamp_: originState.timestamp,\n            gasData_: originState.gasData\n        });\n    }\n\n    /// @dev Child contract should implement the logic for getting the current gas data from the gas oracle\n    /// to be saved as part of the Origin State.\n    // solhint-disable-next-line ordering\n    function _fetchGasData() internal view virtual returns (GasData);\n\n    /// @dev Returns a OriginState struct to save in the contract.\n    function _toOriginState() internal view returns (OriginState memory originState) {\n        originState.blockNumber = ChainContext.blockNumber();\n        originState.timestamp = ChainContext.blockTimestamp();\n        originState.gasData = _fetchGasData();\n    }\n\n    /// @dev Checks that a state and its Origin representation are equal.\n    function _areEqual(State state, OriginState memory originState) internal pure returns (bool) {\n        return state.blockNumber() == originState.blockNumber \u0026\u0026 state.timestamp() == originState.timestamp;\n    }\n}\n\n// contracts/Origin.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Origin` contract is used for sending messages to remote chains. It is done\n/// by inserting the message hashes into the Origin Merkle, which makes it possible to\n/// prove that message was sent using the Merkle proof against the Origin Merkle Root. This essentially\n/// compresses the list of messages into a single 32-byte value that needs to be stored on the destination chain.\n/// `Origin` is responsible for the following:\n/// - Formatting the sent message payloads, and inserting their hashes into the Origin Merkle Tree.\n/// - Keeping track of its own historical states (see parent contract `StateHub`).\n/// - Enforcing minimum tip values for sent base messages based on the provided execution requests.\n/// - Distributing the collected tips upon request from a local `AgentManager` contract.\ncontract Origin is StateHub, OriginEvents, InterfaceOrigin {\n    using MemViewLib for bytes;\n    using MessageLib for bytes;\n    using TipsLib for bytes;\n    using TypeCasts for address;\n\n    address public immutable gasOracle;\n\n    modifier onlyRemoteDestination(uint32 destination) {\n        if (destination == localDomain) revert IncorrectDestinationDomain();\n        _;\n    }\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_, address gasOracle_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {\n        gasOracle = gasOracle_;\n    }\n\n    /// @notice Initializes Origin contract:\n    /// - msg.sender is set as contract owner\n    /// - State of \"empty merkle tree\" is saved\n    function initialize() external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize \"states\": state of an \"empty merkle tree\" is saved\n        _initializeStates();\n    }\n\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable onlyRemoteDestination(destination) returns (uint32 messageNonce, bytes32 messageHash) {\n        // Check that content is not too large\n        if (content.length \u003e MAX_CONTENT_BYTES) revert ContentLengthTooBig();\n        // This will revert if msg.value is lower than value of minimum tips\n        Tips tips = _getMinimumTips(destination, paddedRequest, content.length).matchValue(msg.value);\n        Request request = RequestLib.wrapPadded(paddedRequest);\n        // Format the BaseMessage body\n        bytes memory body = BaseMessageLib.formatBaseMessage({\n            sender_: msg.sender.addressToBytes32(),\n            recipient_: recipient,\n            tips_: tips,\n            request_: request,\n            content_: content\n        });\n        // Send the message\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Base, body);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        onlyAgentManager\n        onlyRemoteDestination(destination)\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // AgentManager (checked via modifier) is responsible for constructing the calldata payload correctly.\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Manager, payload);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function withdrawTips(address recipient, uint256 amount) external onlyAgentManager {\n        if (address(this).balance \u003c amount) revert InsufficientEthBalance();\n        (bool success,) = recipient.call{value: amount}(\"\");\n        if (!success) revert EthTransferFailed();\n        emit TipWithdrawalCompleted(recipient, amount);\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue)\n    {\n        return _getMinimumTips(destination, paddedRequest, contentLength).value();\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Sends the given message to the specified destination. Message hash is inserted\n    /// into the Origin Merkle Tree, which will enable message execution on destination chain.\n    function _sendMessage(uint32 destination, uint32 optimisticPeriod, MessageFlag flag, bytes memory body)\n        internal\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // Format the message header\n        messageNonce = _nextNonce();\n        Header header = flag.encodeHeader({\n            origin_: localDomain,\n            nonce_: messageNonce,\n            destination_: destination,\n            optimisticPeriod_: optimisticPeriod\n        });\n        // Format the full message payload\n        bytes memory msgPayload = MessageLib.formatMessage(header, body);\n        // Insert new leaf into the Origin Merkle Tree and save the updated state\n        messageHash = msgPayload.castToMessage().leaf();\n        _insertAndSave(messageHash);\n        // Emit event with message information\n        emit Sent(messageHash, messageNonce, destination, msgPayload);\n        // Update the gas oracle data. We do this after the provided tips are checked so that\n        // the provided message is sent in the event that the gas oracle data is updated to a higher value.\n        InterfaceGasOracle(gasOracle).updateGasData(destination);\n        // TODO: consider doing this before the message is sent, while adjusting GasOracle.getMinimumTips() to\n        // use the pending gas oracle data.\n    }\n\n    /// @dev Returns the minimum tips for sending a message to the given destination with the given request and content.\n    function _getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        internal\n        view\n        returns (Tips)\n    {\n        return\n            TipsLib.wrapPadded(InterfaceGasOracle(gasOracle).getMinimumTips(destination, paddedRequest, contentLength));\n    }\n\n    /// @dev Gets the current gas data from the gas oracle to be saved as part of the Origin State.\n    function _fetchGasData() internal view override returns (GasData) {\n        return GasDataLib.wrapGasData(InterfaceGasOracle(gasOracle).getGasData());\n    }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"","srcMapRuntime":"","abiDefinition":[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"Contract module which provides access control mechanism, where there is an account (an owner) that can be granted exclusive access to specific functions. By default, the owner account will be the one that deploys the contract. This can later be changed with {transferOwnership} and {acceptOwnership}. This module is used through inheritance. It will make available all functions from parent (Ownable).","kind":"dev","methods":{"acceptOwnership()":{"details":"The new owner accepts the ownership transfer."},"owner()":{"details":"Returns the address of the current owner."},"pendingOwner()":{"details":"Returns the address of the pending owner."},"renounceOwnership()":{"details":"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner."},"transferOwnership(address)":{"details":"Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. Can only be called by the current owner."}},"stateVariables":{"__gap":{"details":"This empty reserved space is put in place to allow future versions to add new variables without shifting down storage in the inheritance chain. See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps"}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferStarted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Contract module which provides access control mechanism, where there is an account (an owner) that can be granted exclusive access to specific functions. By default, the owner account will be the one that deploys the contract. This can later be changed with {transferOwnership} and {acceptOwnership}. This module is used through inheritance. It will make available all functions from parent (Ownable).\",\"kind\":\"dev\",\"methods\":{\"acceptOwnership()\":{\"details\":\"The new owner accepts the ownership transfer.\"},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pendingOwner()\":{\"details\":\"Returns the address of the pending owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. Can only be called by the current owner.\"}},\"stateVariables\":{\"__gap\":{\"details\":\"This empty reserved space is put in place to allow future versions to add new variables without shifting down storage in the inheritance chain. See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Origin.sol\":\"Ownable2StepUpgradeable\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Origin.sol\":{\"keccak256\":\"0x96775924f147f3d1f8df8cdf56731fe52a15af8d8e12e608efb8158c112b18cd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e642a27f5fab3c62b4c02e9754e9e42b1cf2e5381dbea9d3d106d23b7772ebe6\",\"dweb:/ipfs/QmUwn7ZyBvPkjnMuK8ZMSexBUdNQnVtxwyoAyT4DXLQjra\"]}},\"version\":1}"},"hashes":{"acceptOwnership()":"79ba5097","owner()":"8da5cb5b","pendingOwner()":"e30c3978","renounceOwnership()":"715018a6","transferOwnership(address)":"f2fde38b"}},"solidity/Origin.sol:OwnableUpgradeable":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/OriginEvents.sol\n\n/// @notice A collection of events emitted by the Origin contract\nabstract contract OriginEvents {\n    /**\n     * @notice Emitted when a new message is sent.\n     * @param messageHash   Hash of message; the leaf inserted to the Merkle tree for the message\n     * @param nonce         Nonce of sent message (starts from 1)\n     * @param destination   Destination domain\n     * @param message       Raw bytes of message\n     */\n    event Sent(bytes32 indexed messageHash, uint32 indexed nonce, uint32 indexed destination, bytes message);\n\n    /**\n     * @notice Emitted when a tip withdrawal is completed.\n     * @param actor     Actor address\n     * @param tip       Tip value, denominated in local domain's wei\n     */\n    event TipWithdrawalCompleted(address actor, uint256 tip);\n}\n\n// contracts/events/StateHubEvents.sol\n\n/// @notice A collection of events emitted by the StateHub contract\nabstract contract StateHubEvents {\n    /**\n     * @notice Emitted when a new Origin State is saved after a message was sent.\n     * @param state     Raw payload with state data\n     */\n    event StateSaved(bytes state);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n    /**\n     * @notice Check that a given state is valid: matches the historical state of Origin contract.\n     * Note: any Agent including an invalid state in their snapshot will be slashed\n     * upon providing the snapshot and agent signature for it to Origin contract.\n     * @dev Will revert if any of these is true:\n     *  - State payload is not properly formatted.\n     * @param statePayload      Raw payload with state data\n     * @return isValid          Whether the provided state is valid\n     */\n    function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns the amount of saved states so far.\n     * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n     */\n    function statesAmount() external view returns (uint256);\n\n    /**\n     * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @return statePayload     Raw payload with the latest state data\n     */\n    function suggestLatestState() external view returns (bytes memory statePayload);\n\n    /**\n     * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @param nonce             Historical nonce to form a state\n     * @return statePayload     Raw payload with historical state data\n     */\n    function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/InterfaceGasOracle.sol\n\ninterface InterfaceGasOracle {\n    /**\n     * @notice Fetches the latest gas data for the chain from `Destination` contract,\n     * and uses it to update the oracle values for the requested chain.\n     * @param domain    Domain to update the gas data for\n     */\n    function updateGasData(uint32 domain) external;\n\n    /**\n     * @notice Returns the gas data for the local chain.\n     */\n    function getGasData() external view returns (uint256 paddedGasData);\n\n    /**\n     * @notice Returns the gas data for the given domain, in the decoded format.\n     * @param domain        Domain of chain to get gas data for\n     * @return gasPrice     Gas price for the chain (in Wei per gas unit)\n     * @return dataPrice    Calldata price (in Wei per byte of content)\n     * @return execBuffer   Tx fee safety buffer for message execution (in Wei)\n     * @return amortAttCost Amortized cost for attestation submission (in Wei)\n     * @return etherPrice   Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n     * @return markup       Markup for the message execution (in BWAD)\n     */\n    function getDecodedGasData(uint32 domain)\n        external\n        view\n        returns (\n            uint256 gasPrice,\n            uint256 dataPrice,\n            uint256 execBuffer,\n            uint256 amortAttCost,\n            uint256 etherPrice,\n            uint256 markup\n        );\n\n    /**\n     * @notice Returns the minimum tips for sending a message to a given destination.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return paddedTips       Padded encoded minimum tips information\n     */\n    function getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 paddedTips);\n}\n\n// contracts/interfaces/InterfaceOrigin.sol\n\ninterface InterfaceOrigin {\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /**\n     * @notice Send a message to the recipient located on destination domain.\n     * @dev Recipient has to conform to IMessageRecipient interface, otherwise message won't be delivered.\n     * Will revert if any of these is true:\n     * - `destination` is equal to contract's local domain\n     * - `content` length is greater than `MAX_CONTENT_BYTES`\n     * - `msg.value` is lower than value of minimum tips for the given message\n     * @param destination           Domain of destination chain\n     * @param recipient             Address of recipient on destination chain as bytes32\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param paddedRequest         Padded encoded message execution request on destination chain\n     * @param content               Raw bytes content of message\n     * @return messageNonce         Nonce of the sent message\n     * @return messageHash          Hash of the sent message\n     */\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable returns (uint32 messageNonce, bytes32 messageHash);\n\n    /**\n     * @notice Send a manager message to the destination domain.\n     * @dev This could only be called by AgentManager, which takes care of encoding the calldata payload.\n     * Note: (msgOrigin, proofMaturity) security args will be added to payload on the destination chain\n     * so that the AgentManager could verify where the Manager Message came from and how mature is the proof.\n     * Note: function is not payable, as no tips are required for sending a manager message.\n     * Will revert if `destination` is equal to contract's local domain.\n     * @param destination           Domain of destination chain\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param payload               Payload for calling AgentManager on destination chain (with extra security args)\n     */\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        returns (uint32 messageNonce, bytes32 messageHash);\n\n    // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Withdraws locked base message tips to the recipient.\n     * @dev Could only be called by a local AgentManager.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function withdrawTips(address recipient, uint256 amount) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the minimum tips value for sending a message to a given destination.\n     * @dev Using at least `tipsValue` as `msg.value` for `sendBaseMessage()`\n     * will guarantee that the message will be accepted.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return tipsValue        Minimum tips value for a message to be accepted\n     */\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue);\n}\n\n// contracts/libs/Constants.sol\n\n// Here we define common constants to enable their easier reusing later.\n\n// ══════════════════════════════════ MERKLE ═══════════════════════════════════\n/// @dev Height of the Agent Merkle Tree\nuint256 constant AGENT_TREE_HEIGHT = 32;\n/// @dev Height of the Origin Merkle Tree\nuint256 constant ORIGIN_TREE_HEIGHT = 32;\n/// @dev Height of the Snapshot Merkle Tree. Allows up to 64 leafs, e.g. up to 32 states\nuint256 constant SNAPSHOT_TREE_HEIGHT = 6;\n// ══════════════════════════════════ STRUCTS ══════════════════════════════════\n/// @dev See Attestation.sol: (bytes32,bytes32,uint32,uint40,uint40): 32+32+4+5+5\nuint256 constant ATTESTATION_LENGTH = 78;\n/// @dev See GasData.sol: (uint16,uint16,uint16,uint16,uint16,uint16): 2+2+2+2+2+2\nuint256 constant GAS_DATA_LENGTH = 12;\n/// @dev See Receipt.sol: (uint32,uint32,bytes32,bytes32,uint8,address,address,address): 4+4+32+32+1+20+20+20\nuint256 constant RECEIPT_LENGTH = 133;\n/// @dev See State.sol: (bytes32,uint32,uint32,uint40,uint40,GasData): 32+4+4+5+5+len(GasData)\nuint256 constant STATE_LENGTH = 50 + GAS_DATA_LENGTH;\n/// @dev Maximum amount of states in a single snapshot. Each state produces two leafs in the tree\nuint256 constant SNAPSHOT_MAX_STATES = 1 \u003c\u003c (SNAPSHOT_TREE_HEIGHT - 1);\n// ══════════════════════════════════ MESSAGE ══════════════════════════════════\n/// @dev See Header.sol: (uint8,uint32,uint32,uint32,uint32): 1+4+4+4+4\nuint256 constant HEADER_LENGTH = 17;\n/// @dev See Request.sol: (uint96,uint64,uint32): 12+8+4\nuint256 constant REQUEST_LENGTH = 24;\n/// @dev See Tips.sol: (uint64,uint64,uint64,uint64): 8+8+8+8\nuint256 constant TIPS_LENGTH = 32;\n/// @dev The amount of discarded last bits when encoding tip values\nuint256 constant TIPS_GRANULARITY = 32;\n/// @dev Tip values could be only the multiples of TIPS_MULTIPLIER\nuint256 constant TIPS_MULTIPLIER = 1 \u003c\u003c TIPS_GRANULARITY;\n// ══════════════════════════════ STATEMENT SALTS ══════════════════════════════\n/// @dev Salts for signing various statements\nbytes32 constant ATTESTATION_VALID_SALT = keccak256(\"ATTESTATION_VALID_SALT\");\nbytes32 constant ATTESTATION_INVALID_SALT = keccak256(\"ATTESTATION_INVALID_SALT\");\nbytes32 constant RECEIPT_VALID_SALT = keccak256(\"RECEIPT_VALID_SALT\");\nbytes32 constant RECEIPT_INVALID_SALT = keccak256(\"RECEIPT_INVALID_SALT\");\nbytes32 constant SNAPSHOT_VALID_SALT = keccak256(\"SNAPSHOT_VALID_SALT\");\nbytes32 constant STATE_INVALID_SALT = keccak256(\"STATE_INVALID_SALT\");\n// ═════════════════════════════════ PROTOCOL ══════════════════════════════════\n/// @dev Optimistic period for new agent roots in LightManager\nuint32 constant AGENT_ROOT_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Timeout between the agent root could be proposed and resolved in LightManager\nuint32 constant AGENT_ROOT_PROPOSAL_TIMEOUT = 12 hours;\nuint32 constant BONDING_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Amount of time that the Notary will not be considered active after they won a dispute\nuint32 constant DISPUTE_TIMEOUT_NOTARY = 12 hours;\n/// @dev Amount of time without fresh data from Notaries before contract owner can resolve stuck disputes manually\nuint256 constant FRESH_DATA_TIMEOUT = 4 hours;\n/// @dev Maximum bytes per message = 2 KiB (somewhat arbitrarily set to begin)\nuint256 constant MAX_CONTENT_BYTES = 2 * 2 ** 10;\n/// @dev Maximum value for the summit tip that could be set in GasOracle\nuint256 constant MAX_SUMMIT_TIP = 0.01 ether;\n\n// contracts/libs/Errors.sol\n\n// ══════════════════════════════ INVALID CALLER ═══════════════════════════════\n\nerror CallerNotAgentManager();\nerror CallerNotDestination();\nerror CallerNotInbox();\nerror CallerNotSummit();\n\n// ══════════════════════════════ INCORRECT DATA ═══════════════════════════════\n\nerror IncorrectAttestation();\nerror IncorrectAgentDomain();\nerror IncorrectAgentIndex();\nerror IncorrectAgentProof();\nerror IncorrectAgentRoot();\nerror IncorrectDataHash();\nerror IncorrectDestinationDomain();\nerror IncorrectOriginDomain();\nerror IncorrectSnapshotProof();\nerror IncorrectSnapshotRoot();\nerror IncorrectState();\nerror IncorrectStatesAmount();\nerror IncorrectTipsProof();\nerror IncorrectVersionLength();\n\nerror IncorrectNonce();\nerror IncorrectSender();\nerror IncorrectRecipient();\n\nerror FlagOutOfRange();\nerror IndexOutOfRange();\nerror NonceOutOfRange();\n\nerror OutdatedNonce();\n\nerror UnformattedAttestation();\nerror UnformattedAttestationReport();\nerror UnformattedBaseMessage();\nerror UnformattedCallData();\nerror UnformattedCallDataPrefix();\nerror UnformattedMessage();\nerror UnformattedReceipt();\nerror UnformattedReceiptReport();\nerror UnformattedSignature();\nerror UnformattedSnapshot();\nerror UnformattedState();\nerror UnformattedStateReport();\n\n// ═══════════════════════════════ MERKLE TREES ════════════════════════════════\n\nerror LeafNotProven();\nerror MerkleTreeFull();\nerror NotEnoughLeafs();\nerror TreeHeightTooLow();\n\n// ═════════════════════════════ OPTIMISTIC PERIOD ═════════════════════════════\n\nerror BaseClientOptimisticPeriod();\nerror MessageOptimisticPeriod();\nerror SlashAgentOptimisticPeriod();\nerror WithdrawTipsOptimisticPeriod();\nerror ZeroProofMaturity();\n\n// ═══════════════════════════════ AGENT MANAGER ═══════════════════════════════\n\nerror AgentNotGuard();\nerror AgentNotNotary();\n\nerror AgentCantBeAdded();\nerror AgentNotActive();\nerror AgentNotActiveNorUnstaking();\nerror AgentNotFraudulent();\nerror AgentNotUnstaking();\nerror AgentUnknown();\n\nerror AgentRootNotProposed();\nerror AgentRootTimeoutNotOver();\n\nerror NotStuck();\n\nerror DisputeAlreadyResolved();\nerror DisputeNotOpened();\nerror DisputeTimeoutNotOver();\nerror GuardInDispute();\nerror NotaryInDispute();\n\nerror MustBeSynapseDomain();\nerror SynapseDomainForbidden();\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\nerror AlreadyExecuted();\nerror AlreadyFailed();\nerror DuplicatedSnapshotRoot();\nerror IncorrectMagicValue();\nerror GasLimitTooLow();\nerror GasSuppliedTooLow();\n\n// ══════════════════════════════════ ORIGIN ═══════════════════════════════════\n\nerror ContentLengthTooBig();\nerror EthTransferFailed();\nerror InsufficientEthBalance();\n\n// ════════════════════════════════ GAS ORACLE ═════════════════════════════════\n\nerror LocalGasDataNotSet();\nerror RemoteGasDataNotSet();\n\n// ═══════════════════════════════════ TIPS ════════════════════════════════════\n\nerror SummitTipTooHigh();\nerror TipsClaimMoreThanEarned();\nerror TipsClaimZero();\nerror TipsOverflow();\nerror TipsValueTooLow();\n\n// ════════════════════════════════ MEMORY VIEW ════════════════════════════════\n\nerror IndexedTooMuch();\nerror ViewOverrun();\nerror OccupiedMemory();\nerror UnallocatedMemory();\nerror PrecompileOutOfGas();\n\n// ═════════════════════════════════ MULTICALL ═════════════════════════════════\n\nerror MulticallFailed();\n\n// contracts/libs/TypeCasts.sol\n\nlibrary TypeCasts {\n    // alignment preserving cast\n    function addressToBytes32(address addr) internal pure returns (bytes32) {\n        return bytes32(uint256(uint160(addr)));\n    }\n\n    // alignment preserving cast\n    function bytes32ToAddress(bytes32 buf) internal pure returns (address) {\n        return address(uint160(uint256(buf)));\n    }\n}\n\n// contracts/libs/stack/Number.sol\n\n/// Number is a compact representation of uint256, that is fit into 16 bits\n/// with the maximum relative error under 0.4%.\ntype Number is uint16;\n\nusing NumberLib for Number global;\n\n/// # Number\n/// Library for compact representation of uint256 numbers.\n/// - Number is stored using mantissa and exponent, each occupying 8 bits.\n/// - Numbers under 2**8 are stored as `mantissa` with `exponent = 0xFF`.\n/// - Numbers at least 2**8 are approximated as `(256 + mantissa) \u003c\u003c exponent`\n/// \u003e - `0 \u003c= mantissa \u003c 256`\n/// \u003e - `0 \u003c= exponent \u003c= 247` (`256 * 2**248` doesn't fit into uint256)\n/// # Number stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type  | Bytes |\n/// | ---------- | -------- | ----- | ----- |\n/// | (002..001] | mantissa | uint8 | 1     |\n/// | (001..000] | exponent | uint8 | 1     |\n\nlibrary NumberLib {\n    /// @dev Amount of bits to shift to mantissa field\n    uint16 private constant SHIFT_MANTISSA = 8;\n\n    /// @notice For bwad math (binary wad) we use 2**64 as \"wad\" unit.\n    /// @dev We are using not using 10**18 as wad, because it is not stored precisely in NumberLib.\n    uint256 internal constant BWAD_SHIFT = 64;\n    uint256 internal constant BWAD = 1 \u003c\u003c BWAD_SHIFT;\n    /// @notice ~0.1% in bwad units.\n    uint256 internal constant PER_MILLE_SHIFT = BWAD_SHIFT - 10;\n    uint256 internal constant PER_MILLE = 1 \u003c\u003c PER_MILLE_SHIFT;\n\n    /// @notice Compresses uint256 number into 16 bits.\n    function compress(uint256 value) internal pure returns (Number) {\n        // Find `msb` such as `2**msb \u003c= value \u003c 2**(msb + 1)`\n        uint256 msb = mostSignificantBit(value);\n        // We want to preserve 9 bits of precision.\n        // The highest bit is always 1, so we can skip it.\n        // The remaining 8 highest bits are stored as mantissa.\n        if (msb \u003c 8) {\n            // Value is less than 2**8, so we can use value as mantissa with \"-1\" exponent.\n            return _encode(uint8(value), 0xFF);\n        } else {\n            // We use `msb - 8` as exponent otherwise. Note that `exponent \u003e= 0`.\n            unchecked {\n                uint256 exponent = msb - 8;\n                // Shifting right by `msb-8` bits will shift the \"remaining 8 highest bits\" into the 8 lowest bits.\n                // uint8() will truncate the highest bit.\n                return _encode(uint8(value \u003e\u003e exponent), uint8(exponent));\n            }\n        }\n    }\n\n    /// @notice Decompresses 16 bits number into uint256.\n    /// @dev The outcome is an approximation of the original number: `(value - value / 256) \u003c number \u003c= value`.\n    function decompress(Number number) internal pure returns (uint256 value) {\n        // Isolate 8 highest bits as the mantissa.\n        uint256 mantissa = Number.unwrap(number) \u003e\u003e SHIFT_MANTISSA;\n        // This will truncate the highest bits, leaving only the exponent.\n        uint256 exponent = uint8(Number.unwrap(number));\n        if (exponent == 0xFF) {\n            return mantissa;\n        } else {\n            unchecked {\n                return (256 + mantissa) \u003c\u003c (exponent);\n            }\n        }\n    }\n\n    /// @dev Returns the most significant bit of `x`\n    /// https://solidity-by-example.org/bitwise/\n    function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\n        // To find `msb` we determine it bit by bit, starting from the highest one.\n        // `0 \u003c= msb \u003c= 255`, so we start from the highest bit, 1\u003c\u003c7 == 128.\n        // If `x` is at least 2**128, then the highest bit of `x` is at least 128.\n        // solhint-disable no-inline-assembly\n        assembly {\n            // `f` is set to 1\u003c\u003c7 if `x \u003e= 2**128` and to 0 otherwise.\n            let f := shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\n            // If `x \u003e= 2**128` then set `msb` highest bit to 1 and shift `x` right by 128.\n            // Otherwise, `msb` remains 0 and `x` remains unchanged.\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        // `x` is now at most 2**128 - 1. Continue the same way, the next highest bit is 1\u003c\u003c6 == 64.\n        assembly {\n            // `f` is set to 1\u003c\u003c6 if `x \u003e= 2**64` and to 0 otherwise.\n            let f := shl(6, gt(x, 0xFFFFFFFFFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c5 if `x \u003e= 2**32` and to 0 otherwise.\n            let f := shl(5, gt(x, 0xFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c4 if `x \u003e= 2**16` and to 0 otherwise.\n            let f := shl(4, gt(x, 0xFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c3 if `x \u003e= 2**8` and to 0 otherwise.\n            let f := shl(3, gt(x, 0xFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c2 if `x \u003e= 2**4` and to 0 otherwise.\n            let f := shl(2, gt(x, 0xF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c1 if `x \u003e= 2**2` and to 0 otherwise.\n            let f := shl(1, gt(x, 0x3))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1 if `x \u003e= 2**1` and to 0 otherwise.\n            let f := gt(x, 0x1)\n            msb := or(msb, f)\n        }\n    }\n\n    /// @dev Wraps (mantissa, exponent) pair into Number.\n    function _encode(uint8 mantissa, uint8 exponent) private pure returns (Number) {\n        // Casts below are upcasts, so they are safe.\n        return Number.wrap(uint16(mantissa) \u003c\u003c SHIFT_MANTISSA | uint16(exponent));\n    }\n}\n\n// contracts/libs/stack/Request.sol\n\n/// Request is encoded data with \"message execution request\".\ntype Request is uint192;\n\nusing RequestLib for Request global;\n\n/// Library for formatting _the request part_ of _the base messages_.\n/// - Request represents a message sender requirements for the message execution on the destination chain.\n/// - Request occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n/// \u003e gasDrop field is included for future compatibility and is ignored at the moment.\n///\n/// # Request stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type   | Bytes | Description                                          |\n/// | ---------- | -------- | ------ | ----- | ---------------------------------------------------- |\n/// | (024..012] | gasDrop  | uint96 | 12    | Minimum amount of gas token to drop to the recipient |\n/// | (012..004] | gasLimit | uint64 | 8     | Minimum amount of gas units to supply for execution  |\n/// | (004..000] | version  | uint32 | 4     | Base message version to pass to the recipient        |\n\nlibrary RequestLib {\n    /// @dev Amount of bits to shift to gasDrop field\n    uint192 private constant SHIFT_GAS_DROP = 12 * 8;\n    /// @dev Amount of bits to shift to gasLimit field\n    uint192 private constant SHIFT_GAS_LIMIT = 4 * 8;\n\n    /// @notice Returns an encoded request with the given fields\n    /// @param gasDrop_     Minimum amount of gas token to drop to the recipient (ignored at the moment)\n    /// @param gasLimit_    Minimum amount of gas units to supply for execution\n    /// @param version_     Base message version to pass to the recipient\n    function encodeRequest(uint96 gasDrop_, uint64 gasLimit_, uint32 version_) internal pure returns (Request) {\n        // Casts below are upcasts, so they are safe\n        return Request.wrap(uint192(gasDrop_) \u003c\u003c SHIFT_GAS_DROP | uint192(gasLimit_) \u003c\u003c SHIFT_GAS_LIMIT | version_);\n    }\n\n    /// @notice Wraps the padded encoded request into a Request-typed value.\n    /// @dev The \"padded\" request is simply an encoded request casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded requests\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedRequest) internal pure returns (Request) {\n        // Casting to uint192 will truncate the highest bits, which is the behavior we want\n        return Request.wrap(uint192(paddedRequest));\n    }\n\n    /// @notice Returns the requested of gas token to drop to the recipient.\n    function gasDrop(Request request) internal pure returns (uint96) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return uint96(Request.unwrap(request) \u003e\u003e SHIFT_GAS_DROP);\n    }\n\n    /// @notice Returns the requested minimum amount of gas units to supply for execution.\n    function gasLimit(Request request) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Request.unwrap(request) \u003e\u003e SHIFT_GAS_LIMIT);\n    }\n\n    /// @notice Returns the requested base message version to pass to the recipient.\n    function version(Request request) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Request.unwrap(request));\n    }\n}\n\n// node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        require(value \u003c= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        require(value \u003c= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        require(value \u003c= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value \u003c= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        require(value \u003c= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        require(value \u003c= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        require(value \u003c= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        require(value \u003c= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        require(value \u003c= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        require(value \u003c= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        require(value \u003c= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        require(value \u003c= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        require(value \u003c= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        require(value \u003c= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        require(value \u003c= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value \u003c= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        require(value \u003c= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        require(value \u003c= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        require(value \u003c= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value \u003c= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        require(value \u003c= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        require(value \u003c= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        require(value \u003c= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value \u003c= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        require(value \u003c= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        require(value \u003c= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        require(value \u003c= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value \u003c= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        require(value \u003c= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value \u003c= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value \u003c= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     *\n     * _Available since v3.0._\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value \u003e= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     *\n     * _Available since v3.0._\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value \u003c= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     *\n     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length \u003e 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance \u003e= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance \u003e= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length \u003e 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n\n// contracts/base/MultiCallable.sol\n\n/// @notice Collection of Multicall utilities. Fork of Multicall3:\n/// https://github.com/mds1/multicall/blob/master/src/Multicall3.sol\nabstract contract MultiCallable {\n    struct Call {\n        bool allowFailure;\n        bytes callData;\n    }\n\n    struct Result {\n        bool success;\n        bytes returnData;\n    }\n\n    /// @notice Aggregates a few calls to this contract into one multicall without modifying `msg.sender`.\n    function multicall(Call[] calldata calls) external returns (Result[] memory callResults) {\n        uint256 amount = calls.length;\n        callResults = new Result[](amount);\n        Call calldata call_;\n        for (uint256 i = 0; i \u003c amount;) {\n            call_ = calls[i];\n            Result memory result = callResults[i];\n            // We perform a delegate call to ourselves here. Delegate call does not modify `msg.sender`, so\n            // this will have the same effect as if `msg.sender` performed all the calls themselves one by one.\n            // solhint-disable-next-line avoid-low-level-calls\n            (result.success, result.returnData) = address(this).delegatecall(call_.callData);\n            // solhint-disable-next-line no-inline-assembly\n            assembly {\n                // Revert if the call fails and failure is not allowed\n                // `allowFailure := calldataload(call_)` and `success := mload(result)`\n                if iszero(or(calldataload(call_), mload(result))) {\n                    // Revert with `0x4d6a2328` (function selector for `MulticallFailed()`)\n                    mstore(0x00, 0x4d6a232800000000000000000000000000000000000000000000000000000000)\n                    revert(0x00, 0x04)\n                }\n            }\n            unchecked {\n                ++i;\n            }\n        }\n    }\n}\n\n// contracts/base/Version.sol\n\n/**\n * @title Versioned\n * @notice Version getter for contracts. Doesn't use any storage slots, meaning\n * it will never cause any troubles with the upgradeable contracts. For instance, this contract\n * can be added or removed from the inheritance chain without shifting the storage layout.\n */\nabstract contract Versioned {\n    /**\n     * @notice Struct that is mimicking the storage layout of a string with 32 bytes or less.\n     * Length is limited by 32, so the whole string payload takes two memory words:\n     * @param length    String length\n     * @param data      String characters\n     */\n    struct _ShortString {\n        uint256 length;\n        bytes32 data;\n    }\n\n    /// @dev Length of the \"version string\"\n    uint256 private immutable _length;\n    /// @dev Bytes representation of the \"version string\".\n    /// Strings with length over 32 are not supported!\n    bytes32 private immutable _data;\n\n    constructor(string memory version_) {\n        _length = bytes(version_).length;\n        if (_length \u003e 32) revert IncorrectVersionLength();\n        // bytes32 is left-aligned =\u003e this will store the byte representation of the string\n        // with the trailing zeroes to complete the 32-byte word\n        _data = bytes32(bytes(version_));\n    }\n\n    function version() external view returns (string memory versionString) {\n        // Load the immutable values to form the version string\n        _ShortString memory str = _ShortString(_length, _data);\n        // The only way to do this cast is doing some dirty assembly\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            versionString := str\n        }\n    }\n}\n\n// contracts/libs/ChainContext.sol\n\n/// @notice Library for accessing chain context variables as tightly packed integers.\n/// Messaging contracts should rely on this library for accessing chain context variables\n/// instead of doing the casting themselves.\nlibrary ChainContext {\n    using SafeCast for uint256;\n\n    /// @notice Returns the current block number as uint40.\n    /// @dev Reverts if block number is greater than 40 bits, which is not supposed to happen\n    /// until the block.timestamp overflows (assuming block time is at least 1 second).\n    function blockNumber() internal view returns (uint40) {\n        return block.number.toUint40();\n    }\n\n    /// @notice Returns the current block timestamp as uint40.\n    /// @dev Reverts if block timestamp is greater than 40 bits, which is\n    /// supposed to happen approximately in year 36835.\n    function blockTimestamp() internal view returns (uint40) {\n        return block.timestamp.toUint40();\n    }\n\n    /// @notice Returns the chain id as uint32.\n    /// @dev Reverts if chain id is greater than 32 bits, which is not\n    /// supposed to happen in production.\n    function chainId() internal view returns (uint32) {\n        return block.chainid.toUint32();\n    }\n}\n\n// contracts/libs/Structures.sol\n\n// Here we define common enums and structures to enable their easier reusing later.\n\n// ═══════════════════════════════ AGENT STATUS ════════════════════════════════\n\n/// @dev Potential statuses for the off-chain bonded agent:\n/// - Unknown: never provided a bond =\u003e signature not valid\n/// - Active: has a bond in BondingManager =\u003e signature valid\n/// - Unstaking: has a bond in BondingManager, initiated the unstaking =\u003e signature not valid\n/// - Resting: used to have a bond in BondingManager, successfully unstaked =\u003e signature not valid\n/// - Fraudulent: proven to commit fraud, value in Merkle Tree not updated =\u003e signature not valid\n/// - Slashed: proven to commit fraud, value in Merkle Tree was updated =\u003e signature not valid\n/// Unstaked agent could later be added back to THE SAME domain by staking a bond again.\n/// Honest agent: Unknown -\u003e Active -\u003e unstaking -\u003e Resting -\u003e Active ...\n/// Malicious agent: Unknown -\u003e Active -\u003e Fraudulent -\u003e Slashed\n/// Malicious agent: Unknown -\u003e Active -\u003e Unstaking -\u003e Fraudulent -\u003e Slashed\nenum AgentFlag {\n    Unknown,\n    Active,\n    Unstaking,\n    Resting,\n    Fraudulent,\n    Slashed\n}\n\n/// @notice Struct for storing an agent in the BondingManager contract.\nstruct AgentStatus {\n    AgentFlag flag;\n    uint32 domain;\n    uint32 index;\n}\n// 184 bits available for tight packing\n\nusing StructureUtils for AgentStatus global;\n\n/// @notice Potential statuses of an agent in terms of being in dispute\n/// - None: agent is not in dispute\n/// - Pending: agent is in unresolved dispute\n/// - Slashed: agent was in dispute that lead to agent being slashed\n/// Note: agent who won the dispute has their status reset to None\nenum DisputeFlag {\n    None,\n    Pending,\n    Slashed\n}\n\n/// @notice Struct for storing dispute status of an agent.\n/// @param flag         Dispute flag: None/Pending/Slashed.\n/// @param openedAt     Timestamp when the latest agent dispute was opened (zero if not opened).\n/// @param resolvedAt   Timestamp when the latest agent dispute was resolved (zero if not resolved).\nstruct DisputeStatus {\n    DisputeFlag flag;\n    uint40 openedAt;\n    uint40 resolvedAt;\n}\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\n/// @notice Struct representing the status of Destination contract.\n/// @param snapRootTime     Timestamp when latest snapshot root was accepted\n/// @param agentRootTime    Timestamp when latest agent root was accepted\n/// @param notaryIndex      Index of Notary who signed the latest agent root\nstruct DestinationStatus {\n    uint40 snapRootTime;\n    uint40 agentRootTime;\n    uint32 notaryIndex;\n}\n\n// ═══════════════════════════════ EXECUTION HUB ═══════════════════════════════\n\n/// @notice Potential statuses of the message in Execution Hub.\n/// - None: there hasn't been a valid attempt to execute the message yet\n/// - Failed: there was a valid attempt to execute the message, but recipient reverted\n/// - Success: there was a valid attempt to execute the message, and recipient did not revert\n/// Note: message can be executed until its status is Success\nenum MessageStatus {\n    None,\n    Failed,\n    Success\n}\n\nlibrary StructureUtils {\n    /// @notice Checks that Agent is Active\n    function verifyActive(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active) {\n            revert AgentNotActive();\n        }\n    }\n\n    /// @notice Checks that Agent is Unstaking\n    function verifyUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Unstaking) {\n            revert AgentNotUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Active or Unstaking\n    function verifyActiveUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active \u0026\u0026 status.flag != AgentFlag.Unstaking) {\n            revert AgentNotActiveNorUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Fraudulent\n    function verifyFraudulent(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Fraudulent) {\n            revert AgentNotFraudulent();\n        }\n    }\n\n    /// @notice Checks that Agent is not Unknown\n    function verifyKnown(AgentStatus memory status) internal pure {\n        if (status.flag == AgentFlag.Unknown) {\n            revert AgentUnknown();\n        }\n    }\n}\n\n// contracts/libs/memory/MemView.sol\n\n/// @dev MemView is an untyped view over a portion of memory to be used instead of `bytes memory`\ntype MemView is uint256;\n\n/// @dev Attach library functions to MemView\nusing MemViewLib for MemView global;\n\n/// @notice Library for operations with the memory views.\n/// Forked from https://github.com/summa-tx/memview-sol with several breaking changes:\n/// - The codebase is ported to Solidity 0.8\n/// - Custom errors are added\n/// - The runtime type checking is replaced with compile-time check provided by User-Defined Value Types\n///   https://docs.soliditylang.org/en/latest/types.html#user-defined-value-types\n/// - uint256 is used as the underlying type for the \"memory view\" instead of bytes29.\n///   It is wrapped into MemView custom type in order not to be confused with actual integers.\n/// - Therefore the \"type\" field is discarded, allowing to allocate 16 bytes for both view location and length\n/// - The documentation is expanded\n/// - Library functions unused by the rest of the codebase are removed\n//  - Very pretty code separators are added :)\nlibrary MemViewLib {\n    /// @notice Stack layout for uint256 (from highest bits to lowest)\n    /// (32 .. 16]      loc     16 bytes    Memory address of underlying bytes\n    /// (16 .. 00]      len     16 bytes    Length of underlying bytes\n\n    // ═══════════════════════════════════════════ BUILDING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Instantiate a new untyped memory view. This should generally not be called directly.\n     * Prefer `ref` wherever possible.\n     * @param loc_          The memory address\n     * @param len_          The length\n     * @return The new view with the specified location and length\n     */\n    function build(uint256 loc_, uint256 len_) internal pure returns (MemView) {\n        uint256 end_ = loc_ + len_;\n        // Make sure that a view is not constructed that points to unallocated memory\n        // as this could be indicative of a buffer overflow attack\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            if gt(end_, mload(0x40)) { end_ := 0 }\n        }\n        if (end_ == 0) {\n            revert UnallocatedMemory();\n        }\n        return _unsafeBuildUnchecked(loc_, len_);\n    }\n\n    /**\n     * @notice Instantiate a memory view from a byte array.\n     * @dev Note that due to Solidity memory representation, it is not possible to\n     * implement a deref, as the `bytes` type stores its len in memory.\n     * @param arr           The byte array\n     * @return The memory view over the provided byte array\n     */\n    function ref(bytes memory arr) internal pure returns (MemView) {\n        uint256 len_ = arr.length;\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 loc_;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // We add 0x20, so that the view starts exactly where the array data starts\n            loc_ := add(arr, 0x20)\n        }\n        return build(loc_, len_);\n    }\n\n    // ════════════════════════════════════════════ CLONING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to the new memory.\n     * @param memView       The memory view\n     * @return arr          The cloned byte array\n     */\n    function clone(MemView memView) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        unchecked {\n            _unsafeCopyTo(memView, ptr + 0x20);\n        }\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 len_ = memView.len();\n        uint256 footprint_ = memView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    /**\n     * @notice Copies all views, joins them into a new bytearray.\n     * @param memViews      The memory views\n     * @return arr          The new byte array with joined data behind the given views\n     */\n    function join(MemView[] memory memViews) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        MemView newView;\n        unchecked {\n            newView = _unsafeJoin(memViews, ptr + 0x20);\n        }\n        uint256 len_ = newView.len();\n        uint256 footprint_ = newView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    // ══════════════════════════════════════════ INSPECTING MEMORY VIEW ═══════════════════════════════════════════════\n\n    /**\n     * @notice Returns the memory address of the underlying bytes.\n     * @param memView       The memory view\n     * @return loc_         The memory address\n     */\n    function loc(MemView memView) internal pure returns (uint256 loc_) {\n        // loc is stored in the highest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u003e\u003e 128;\n    }\n\n    /**\n     * @notice Returns the number of bytes of the view.\n     * @param memView       The memory view\n     * @return len_         The length of the view\n     */\n    function len(MemView memView) internal pure returns (uint256 len_) {\n        // len is stored in the lowest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u0026 type(uint128).max;\n    }\n\n    /**\n     * @notice Returns the endpoint of `memView`.\n     * @param memView       The memory view\n     * @return end_         The endpoint of `memView`\n     */\n    function end(MemView memView) internal pure returns (uint256 end_) {\n        // The endpoint never overflows uint128, let alone uint256, so we could use unchecked math here\n        unchecked {\n            return memView.loc() + memView.len();\n        }\n    }\n\n    /**\n     * @notice Returns the number of memory words this memory view occupies, rounded up.\n     * @param memView       The memory view\n     * @return words_       The number of memory words\n     */\n    function words(MemView memView) internal pure returns (uint256 words_) {\n        // returning ceil(length / 32.0)\n        unchecked {\n            return (memView.len() + 31) \u003e\u003e 5;\n        }\n    }\n\n    /**\n     * @notice Returns the in-memory footprint of a fresh copy of the view.\n     * @param memView       The memory view\n     * @return footprint_   The in-memory footprint of a fresh copy of the view.\n     */\n    function footprint(MemView memView) internal pure returns (uint256 footprint_) {\n        // words() * 32\n        return memView.words() \u003c\u003c 5;\n    }\n\n    // ════════════════════════════════════════════ HASHING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the keccak256 hash of the underlying memory\n     * @param memView       The memory view\n     * @return digest       The keccak256 hash of the underlying memory\n     */\n    function keccak(MemView memView) internal pure returns (bytes32 digest) {\n        uint256 loc_ = memView.loc();\n        uint256 len_ = memView.len();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            digest := keccak256(loc_, len_)\n        }\n    }\n\n    /**\n     * @notice Adds a salt to the keccak256 hash of the underlying data and returns the keccak256 hash of the\n     * resulting data.\n     * @param memView       The memory view\n     * @return digestSalted keccak256(salt, keccak256(memView))\n     */\n    function keccakSalted(MemView memView, bytes32 salt) internal pure returns (bytes32 digestSalted) {\n        return keccak256(bytes.concat(salt, memView.keccak()));\n    }\n\n    // ════════════════════════════════════════════ SLICING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Safe slicing without memory modification.\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the given index\n     */\n    function slice(MemView memView, uint256 index_, uint256 len_) internal pure returns (MemView) {\n        uint256 loc_ = memView.loc();\n        // Ensure it doesn't overrun the view\n        if (loc_ + index_ + len_ \u003e memView.end()) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // loc_ + index_ \u003c= memView.end()\n            return build({loc_: loc_ + index_, len_: len_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing bytes from `index` to end(memView).\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @return The new view for the slice starting from the given index until the initial view endpoint\n     */\n    function sliceFrom(MemView memView, uint256 index_) internal pure returns (MemView) {\n        uint256 len_ = memView.len();\n        // Ensure it doesn't overrun the view\n        if (index_ \u003e len_) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // index_ \u003c= len_ =\u003e memView.loc() + index_ \u003c= memView.loc() + memView.len() == memView.end()\n            return build({loc_: memView.loc() + index_, len_: len_ - index_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the first `len` bytes.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the initial view beginning\n     */\n    function prefix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        return memView.slice({index_: 0, len_: len_});\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the last `len` byte.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length until the initial view endpoint\n     */\n    function postfix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        uint256 viewLen = memView.len();\n        // Ensure it doesn't overrun the view\n        if (len_ \u003e viewLen) {\n            revert ViewOverrun();\n        }\n        // Could do the unchecked math due to the check above\n        uint256 index_;\n        unchecked {\n            index_ = viewLen - len_;\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // len_ \u003c= memView.len() =\u003e memView.loc() \u003c= loc_ \u003c= memView.end()\n            return build({loc_: memView.loc() + viewLen - len_, len_: len_});\n        }\n    }\n\n    // ═══════════════════════════════════════════ INDEXING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Load up to 32 bytes from the view onto the stack.\n     * @dev Returns a bytes32 with only the `bytes_` HIGHEST bytes set.\n     * This can be immediately cast to a smaller fixed-length byte array.\n     * To automatically cast to an integer, use `indexUint`.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return result       The 32 byte result having only `bytes_` highest bytes set\n     */\n    function index(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (bytes32 result) {\n        if (bytes_ == 0) {\n            return bytes32(0);\n        }\n        // Can't load more than 32 bytes to the stack in one go\n        if (bytes_ \u003e 32) {\n            revert IndexedTooMuch();\n        }\n        // The last indexed byte should be within view boundaries\n        if (index_ + bytes_ \u003e memView.len()) {\n            revert ViewOverrun();\n        }\n        uint256 bitLength = bytes_ \u003c\u003c 3; // bytes_ * 8\n        uint256 loc_ = memView.loc();\n        // Get a mask with `bitLength` highest bits set\n        uint256 mask;\n        // 0x800...00 binary representation is 100...00\n        // sar stands for \"signed arithmetic shift\": https://en.wikipedia.org/wiki/Arithmetic_shift\n        // sar(N-1, 100...00) = 11...100..00, with exactly N highest bits set to 1\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            mask := sar(sub(bitLength, 1), 0x8000000000000000000000000000000000000000000000000000000000000000)\n        }\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load a full word using index offset, and apply mask to ignore non-relevant bytes\n            result := and(mload(add(loc_, index_)), mask)\n        }\n    }\n\n    /**\n     * @notice Parse an unsigned integer from the view at `index`.\n     * @dev Requires that the view have \u003e= `bytes_` bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return The unsigned integer\n     */\n    function indexUint(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (uint256) {\n        bytes32 indexedBytes = memView.index(index_, bytes_);\n        // `index()` returns left-aligned `bytes_`, while integers are right-aligned\n        // Shifting here to right-align with the full 32 bytes word: need to shift right `(32 - bytes_)` bytes\n        unchecked {\n            // memView.index() reverts when bytes_ \u003e 32, thus unchecked math\n            return uint256(indexedBytes) \u003e\u003e ((32 - bytes_) \u003c\u003c 3);\n        }\n    }\n\n    /**\n     * @notice Parse an address from the view at `index`.\n     * @dev Requires that the view have \u003e= 20 bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @return The address\n     */\n    function indexAddress(MemView memView, uint256 index_) internal pure returns (address) {\n        // index 20 bytes as `uint160`, and then cast to `address`\n        return address(uint160(memView.indexUint(index_, 20)));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns a memory view over the specified memory location\n    /// without checking if it points to unallocated memory.\n    function _unsafeBuildUnchecked(uint256 loc_, uint256 len_) private pure returns (MemView) {\n        // There is no scenario where loc or len would overflow uint128, so we omit this check.\n        // We use the highest 128 bits to encode the location and the lowest 128 bits to encode the length.\n        return MemView.wrap((loc_ \u003c\u003c 128) | len_);\n    }\n\n    /**\n     * @notice Copy the view to a location, return an unsafe memory reference\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memView       The memory view\n     * @param newLoc        The new location to copy the underlying view data\n     * @return The memory view over the unsafe memory with the copied underlying data\n     */\n    function _unsafeCopyTo(MemView memView, uint256 newLoc) private view returns (MemView) {\n        uint256 len_ = memView.len();\n        uint256 oldLoc = memView.loc();\n\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (newLoc \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        bool res;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // use the identity precompile (0x04) to copy\n            res := staticcall(gas(), 0x04, oldLoc, len_, newLoc, len_)\n        }\n        if (!res) revert PrecompileOutOfGas();\n        return _unsafeBuildUnchecked({loc_: newLoc, len_: len_});\n    }\n\n    /**\n     * @notice Join the views in memory, return an unsafe reference to the memory.\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memViews      The memory views\n     * @return The conjoined view pointing to the new memory\n     */\n    function _unsafeJoin(MemView[] memory memViews, uint256 location) private view returns (MemView) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (location \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        // Copy the views to the specified location one by one, by tracking the amount of copied bytes so far\n        uint256 offset = 0;\n        for (uint256 i = 0; i \u003c memViews.length;) {\n            MemView memView = memViews[i];\n            // We can use the unchecked math here as location + sum(view.length) will never overflow uint256\n            unchecked {\n                _unsafeCopyTo(memView, location + offset);\n                offset += memView.len();\n                ++i;\n            }\n        }\n        return _unsafeBuildUnchecked({loc_: location, len_: offset});\n    }\n}\n\n// contracts/libs/merkle/MerkleMath.sol\n\nlibrary MerkleMath {\n    // ═════════════════════════════════════════ BASIC MERKLE CALCULATIONS ═════════════════════════════════════════════\n\n    /**\n     * @notice Calculates the merkle root for the given leaf and merkle proof.\n     * @dev Will revert if proof length exceeds the tree height.\n     * @param index     Index of `leaf` in tree\n     * @param leaf      Leaf of the merkle tree\n     * @param proof     Proof of inclusion of `leaf` in the tree\n     * @param height    Height of the merkle tree\n     * @return root_    Calculated Merkle Root\n     */\n    function proofRoot(uint256 index, bytes32 leaf, bytes32[] memory proof, uint256 height)\n        internal\n        pure\n        returns (bytes32 root_)\n    {\n        // Proof length could not exceed the tree height\n        uint256 proofLen = proof.length;\n        if (proofLen \u003e height) revert TreeHeightTooLow();\n        root_ = leaf;\n        /// @dev Apply unchecked to all ++h operations\n        unchecked {\n            // Go up the tree levels from the leaf following the proof\n            for (uint256 h = 0; h \u003c proofLen; ++h) {\n                // Get a sibling node on current level: this is proof[h]\n                root_ = getParent(root_, proof[h], index, h);\n            }\n            // Go up to the root: the remaining siblings are EMPTY\n            for (uint256 h = proofLen; h \u003c height; ++h) {\n                root_ = getParent(root_, bytes32(0), index, h);\n            }\n        }\n    }\n\n    /**\n     * @notice Calculates the parent of a node on the path from one of the leafs to root.\n     * @param node          Node on a path from tree leaf to root\n     * @param sibling       Sibling for a given node\n     * @param leafIndex     Index of the tree leaf\n     * @param nodeHeight    \"Level height\" for `node` (ZERO for leafs, ORIGIN_TREE_HEIGHT for root)\n     */\n    function getParent(bytes32 node, bytes32 sibling, uint256 leafIndex, uint256 nodeHeight)\n        internal\n        pure\n        returns (bytes32 parent)\n    {\n        // Index for `node` on its \"tree level\" is (leafIndex / 2**height)\n        // \"Left child\" has even index, \"right child\" has odd index\n        if ((leafIndex \u003e\u003e nodeHeight) \u0026 1 == 0) {\n            // Left child\n            return getParent(node, sibling);\n        } else {\n            // Right child\n            return getParent(sibling, node);\n        }\n    }\n\n    /// @notice Calculates the parent of tow nodes in the merkle tree.\n    /// @dev We use implementation with H(0,0) = 0\n    /// This makes EVERY empty node in the tree equal to ZERO,\n    /// saving us from storing H(0,0), H(H(0,0), H(0, 0)), and so on\n    /// @param leftChild    Left child of the calculated node\n    /// @param rightChild   Right child of the calculated node\n    /// @return parent      Value for the node having above mentioned children\n    function getParent(bytes32 leftChild, bytes32 rightChild) internal pure returns (bytes32 parent) {\n        if (leftChild == bytes32(0) \u0026\u0026 rightChild == bytes32(0)) {\n            return 0;\n        } else {\n            return keccak256(bytes.concat(leftChild, rightChild));\n        }\n    }\n\n    // ════════════════════════════════ ROOT/PROOF CALCULATION FOR A LIST OF LEAFS ═════════════════════════════════════\n\n    /**\n     * @notice Calculates merkle root for a list of given leafs.\n     * Merkle Tree is constructed by padding the list with ZERO values for leafs until list length is `2**height`.\n     * Merkle Root is calculated for the constructed tree, and then saved in `leafs[0]`.\n     * \u003e Note:\n     * \u003e - `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * \u003e - Caller is expected not to reuse `hashes` list after the call, and only use `leafs[0]` value,\n     * which is guaranteed to contain the calculated merkle root.\n     * \u003e - root is calculated using the `H(0,0) = 0` Merkle Tree implementation. See MerkleTree.sol for details.\n     * @dev Amount of leaves should be at most `2**height`\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param height    Height of the Merkle Tree to construct\n     */\n    function calculateRoot(bytes32[] memory hashes, uint256 height) internal pure {\n        uint256 levelLength = hashes.length;\n        // Amount of hashes could not exceed amount of leafs in tree with the given height\n        if (levelLength \u003e (1 \u003c\u003c height)) revert TreeHeightTooLow();\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\": the amount of iterations for the for loop above.\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n            }\n        }\n    }\n\n    /**\n     * @notice Generates a proof of inclusion of a leaf in the list. If the requested index is outside\n     * of the list range, generates a proof of inclusion for an empty leaf (proof of non-inclusion).\n     * The Merkle Tree is constructed by padding the list with ZERO values until list length is a power of two\n     * __AND__ index is in the extended list range. For example:\n     *  - `hashes.length == 6` and `0 \u003c= index \u003c= 7` will \"extend\" the list to 8 entries.\n     *  - `hashes.length == 6` and `7 \u003c index \u003c= 15` will \"extend\" the list to 16 entries.\n     * \u003e Note: `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * Caller is expected not to reuse `hashes` list after the call.\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param index     Leaf index to generate the proof for\n     * @return proof    Generated merkle proof\n     */\n    function calculateProof(bytes32[] memory hashes, uint256 index) internal pure returns (bytes32[] memory proof) {\n        // Use only meaningful values for the shortened proof\n        // Check if index is within the list range (we want to generates proofs for outside leafs as well)\n        uint256 height = getHeight(index \u003c hashes.length ? hashes.length : (index + 1));\n        proof = new bytes32[](height);\n        uint256 levelLength = hashes.length;\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Use sibling for the merkle proof; `index^1` is index of our sibling\n                proof[h] = (index ^ 1 \u003c levelLength) ? hashes[index ^ 1] : bytes32(0);\n\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\"\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n                // Traverse to parent node\n                index \u003e\u003e= 1;\n            }\n        }\n    }\n\n    /// @notice Returns the height of the tree having a given amount of leafs.\n    function getHeight(uint256 leafs) internal pure returns (uint256 height) {\n        uint256 amount = 1;\n        while (amount \u003c leafs) {\n            unchecked {\n                ++height;\n            }\n            amount \u003c\u003c= 1;\n        }\n    }\n}\n\n// contracts/libs/stack/GasData.sol\n\n/// GasData in encoded data with \"basic information about gas prices\" for some chain.\ntype GasData is uint96;\n\nusing GasDataLib for GasData global;\n\n/// ChainGas is encoded data with given chain's \"basic information about gas prices\".\ntype ChainGas is uint128;\n\nusing GasDataLib for ChainGas global;\n\n/// Library for encoding and decoding GasData and ChainGas structs.\n/// # GasData\n/// `GasData` is a struct to store the \"basic information about gas prices\", that could\n/// be later used to approximate the cost of a message execution, and thus derive the\n/// minimal tip values for sending a message to the chain.\n/// \u003e - `GasData` is supposed to be cached by `GasOracle` contract, allowing to store the\n/// \u003e approximates instead of the exact values, and thus save on storage costs.\n/// \u003e - For instance, if `GasOracle` only updates the values on +- 10% change, having an\n/// \u003e 0.4% error on the approximates would be acceptable.\n/// `GasData` is supposed to be included in the Origin's state, which are synced across\n/// chains using Agent-signed snapshots and attestations.\n/// ## GasData stack layout (from highest bits to lowest)\n///\n/// | Position   | Field        | Type   | Bytes | Description                                         |\n/// | ---------- | ------------ | ------ | ----- | --------------------------------------------------- |\n/// | (012..010] | gasPrice     | uint16 | 2     | Gas price for the chain (in Wei per gas unit)       |\n/// | (010..008] | dataPrice    | uint16 | 2     | Calldata price (in Wei per byte of content)         |\n/// | (008..006] | execBuffer   | uint16 | 2     | Tx fee safety buffer for message execution (in Wei) |\n/// | (006..004] | amortAttCost | uint16 | 2     | Amortized cost for attestation submission (in Wei)  |\n/// | (004..002] | etherPrice   | uint16 | 2     | Chain's Ether Price / Mainnet Ether Price (in BWAD) |\n/// | (002..000] | markup       | uint16 | 2     | Markup for the message execution (in BWAD)          |\n/// \u003e See Number.sol for more details on `Number` type and BWAD (binary WAD) math.\n///\n/// ## ChainGas stack layout (from highest bits to lowest)\n///\n/// | Position   | Field   | Type   | Bytes | Description      |\n/// | ---------- | ------- | ------ | ----- | ---------------- |\n/// | (016..004] | gasData | uint96 | 12    | Chain's gas data |\n/// | (004..000] | domain  | uint32 | 4     | Chain's domain   |\nlibrary GasDataLib {\n    /// @dev Amount of bits to shift to gasPrice field\n    uint96 private constant SHIFT_GAS_PRICE = 10 * 8;\n    /// @dev Amount of bits to shift to dataPrice field\n    uint96 private constant SHIFT_DATA_PRICE = 8 * 8;\n    /// @dev Amount of bits to shift to execBuffer field\n    uint96 private constant SHIFT_EXEC_BUFFER = 6 * 8;\n    /// @dev Amount of bits to shift to amortAttCost field\n    uint96 private constant SHIFT_AMORT_ATT_COST = 4 * 8;\n    /// @dev Amount of bits to shift to etherPrice field\n    uint96 private constant SHIFT_ETHER_PRICE = 2 * 8;\n\n    /// @dev Amount of bits to shift to gasData field\n    uint128 private constant SHIFT_GAS_DATA = 4 * 8;\n\n    // ═════════════════════════════════════════════════ GAS DATA ══════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded GasData struct with the given fields.\n    /// @param gasPrice_        Gas price for the chain (in Wei per gas unit)\n    /// @param dataPrice_       Calldata price (in Wei per byte of content)\n    /// @param execBuffer_      Tx fee safety buffer for message execution (in Wei)\n    /// @param amortAttCost_    Amortized cost for attestation submission (in Wei)\n    /// @param etherPrice_      Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n    /// @param markup_          Markup for the message execution (in BWAD)\n    function encodeGasData(\n        Number gasPrice_,\n        Number dataPrice_,\n        Number execBuffer_,\n        Number amortAttCost_,\n        Number etherPrice_,\n        Number markup_\n    ) internal pure returns (GasData) {\n        // Number type wraps uint16, so could safely be casted to uint96\n        // forgefmt: disable-next-item\n        return GasData.wrap(\n            uint96(Number.unwrap(gasPrice_)) \u003c\u003c SHIFT_GAS_PRICE |\n            uint96(Number.unwrap(dataPrice_)) \u003c\u003c SHIFT_DATA_PRICE |\n            uint96(Number.unwrap(execBuffer_)) \u003c\u003c SHIFT_EXEC_BUFFER |\n            uint96(Number.unwrap(amortAttCost_)) \u003c\u003c SHIFT_AMORT_ATT_COST |\n            uint96(Number.unwrap(etherPrice_)) \u003c\u003c SHIFT_ETHER_PRICE |\n            uint96(Number.unwrap(markup_))\n        );\n    }\n\n    /// @notice Wraps padded uint256 value into GasData struct.\n    function wrapGasData(uint256 paddedGasData) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(paddedGasData));\n    }\n\n    /// @notice Returns the gas price, in Wei per gas unit.\n    function gasPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_GAS_PRICE));\n    }\n\n    /// @notice Returns the calldata price, in Wei per byte of content.\n    function dataPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_DATA_PRICE));\n    }\n\n    /// @notice Returns the tx fee safety buffer for message execution, in Wei.\n    function execBuffer(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_EXEC_BUFFER));\n    }\n\n    /// @notice Returns the amortized cost for attestation submission, in Wei.\n    function amortAttCost(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_AMORT_ATT_COST));\n    }\n\n    /// @notice Returns the ratio of Chain's Ether Price / Mainnet Ether Price, in BWAD math.\n    function etherPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_ETHER_PRICE));\n    }\n\n    /// @notice Returns the markup for the message execution, in BWAD math.\n    function markup(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data)));\n    }\n\n    // ════════════════════════════════════════════════ CHAIN DATA ═════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded ChainGas struct with the given fields.\n    /// @param gasData_ Chain's gas data\n    /// @param domain_  Chain's domain\n    function encodeChainGas(GasData gasData_, uint32 domain_) internal pure returns (ChainGas) {\n        // GasData type wraps uint96, so could safely be casted to uint128\n        return ChainGas.wrap(uint128(GasData.unwrap(gasData_)) \u003c\u003c SHIFT_GAS_DATA | uint128(domain_));\n    }\n\n    /// @notice Wraps padded uint256 value into ChainGas struct.\n    function wrapChainGas(uint256 paddedChainGas) internal pure returns (ChainGas) {\n        // Casting to uint128 will truncate the highest bits, which is the behavior we want\n        return ChainGas.wrap(uint128(paddedChainGas));\n    }\n\n    /// @notice Returns the chain's gas data.\n    function gasData(ChainGas data) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(ChainGas.unwrap(data) \u003e\u003e SHIFT_GAS_DATA));\n    }\n\n    /// @notice Returns the chain's domain.\n    function domain(ChainGas data) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(ChainGas.unwrap(data));\n    }\n\n    /// @notice Returns the hash for the list of ChainGas structs.\n    function snapGasHash(ChainGas[] memory snapGas) internal pure returns (bytes32 snapGasHash_) {\n        // Use assembly to calculate the hash of the array without copying it\n        // ChainGas takes a single word of storage, thus ChainGas[] is stored in the following way:\n        // 0x00: length of the array, in words\n        // 0x20: first ChainGas struct\n        // 0x40: second ChainGas struct\n        // And so on...\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Find the location where the array data starts, we add 0x20 to skip the length field\n            let loc := add(snapGas, 0x20)\n            // Load the length of the array (in words).\n            // Shifting left 5 bits is equivalent to multiplying by 32: this converts from words to bytes.\n            let len := shl(5, mload(snapGas))\n            // Calculate the hash of the array\n            snapGasHash_ := keccak256(loc, len)\n        }\n    }\n}\n\n// contracts/libs/stack/Header.sol\n\n/// Header is encoded data with \"general routing information\".\ntype Header is uint136;\n\nusing HeaderLib for Header global;\n\n/// Types of messages supported by Origin-Destination\n/// - Base: message sent by protocol user, contains tips\n/// - Manager: message sent between AgentManager contracts located on different chains, no tips\nenum MessageFlag {\n    Base,\n    Manager\n}\n\nusing HeaderLib for MessageFlag global;\n\n/// Library for formatting _the header part_ of _the messages used by Origin and Destination_.\n/// - Header represents general information for routing a Message for Origin and Destination.\n/// - Header occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n///\n/// # Header stack layout (from highest bits to lowest)\n///\n/// | Position   | Field            | Type   | Bytes | Description                             |\n/// | ---------- | ---------------- | ------ | ----- | --------------------------------------- |\n/// | (017..016] | flag             | uint8  | 1     | Flag specifying the type of message     |\n/// | (016..012] | origin           | uint32 | 4     | Domain where message originated         |\n/// | (012..008] | nonce            | uint32 | 4     | Message nonce on the origin domain      |\n/// | (008..004] | destination      | uint32 | 4     | Domain where message will be executed   |\n/// | (004..000] | optimisticPeriod | uint32 | 4     | Optimistic period that will be enforced |\nlibrary HeaderLib {\n    /// @dev Amount of bits to shift to flag field\n    uint136 private constant SHIFT_FLAG = 16 * 8;\n    /// @dev Amount of bits to shift to origin field\n    uint136 private constant SHIFT_ORIGIN = 12 * 8;\n    /// @dev Amount of bits to shift to nonce field\n    uint136 private constant SHIFT_NONCE = 8 * 8;\n    /// @dev Amount of bits to shift to destination field\n    uint136 private constant SHIFT_DESTINATION = 4 * 8;\n\n    /// @notice Returns an encoded header with provided fields\n    /// @param origin_              Domain of origin chain\n    /// @param nonce_               Message nonce on origin chain\n    /// @param destination_         Domain of destination chain\n    /// @param optimisticPeriod_    Optimistic period for message execution\n    function encodeHeader(\n        MessageFlag flag_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint32 destination_,\n        uint32 optimisticPeriod_\n    ) internal pure returns (Header) {\n        // All casts below are upcasts, so they are safe\n        // forgefmt: disable-next-item\n        return Header.wrap(\n            uint136(uint8(flag_)) \u003c\u003c SHIFT_FLAG |\n            uint136(origin_) \u003c\u003c SHIFT_ORIGIN |\n            uint136(nonce_) \u003c\u003c SHIFT_NONCE |\n            uint136(destination_) \u003c\u003c SHIFT_DESTINATION |\n            uint136(optimisticPeriod_)\n        );\n    }\n\n    /// @notice Checks that the header is a valid encoded header.\n    function isHeader(uint256 paddedHeader) internal pure returns (bool) {\n        // Check that flag is within range\n        return _flag(paddedHeader) \u003c= uint8(type(MessageFlag).max);\n    }\n\n    /// @notice Wraps the padded encoded request into a Header-typed value.\n    /// @dev The \"padded\" header is simply an encoded header casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded headers\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedHeader) internal pure returns (Header) {\n        // Check that flag is within range\n        if (!isHeader(paddedHeader)) revert FlagOutOfRange();\n        // Casting to uint136 will truncate the highest bits, which is the behavior we want\n        return Header.wrap(uint136(paddedHeader));\n    }\n\n    /// @notice Returns header's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Header header) internal pure returns (bytes32 hashedHeader) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store header in scratch space\n            mstore(0, header)\n            // Compute hash of header padded to 32 bytes\n            hashedHeader := keccak256(0, 32)\n        }\n    }\n\n    // ══════════════════════════════════════════════ HEADER SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns header's flag field\n    function flag(Header header) internal pure returns (MessageFlag) {\n        // We check that flag is within range when wrapping the header, so this cast is safe\n        return MessageFlag(_flag(Header.unwrap(header)));\n    }\n\n    /// @notice Returns header's origin field\n    function origin(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_ORIGIN);\n    }\n\n    /// @notice Returns header's nonce field\n    function nonce(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_NONCE);\n    }\n\n    /// @notice Returns header's destination field\n    function destination(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_DESTINATION);\n    }\n\n    /// @notice Returns header's optimistic seconds field\n    function optimisticPeriod(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns header's flag field without casting to MessageFlag\n    function _flag(uint256 paddedHeader) private pure returns (uint8) {\n        // Casting to uint8 will truncate the highest bits, which is the behavior we want\n        return uint8(paddedHeader \u003e\u003e SHIFT_FLAG);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n     * constructor.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall \u0026\u0026 _initialized \u003c 1) || (!AddressUpgradeable.isContract(address(this)) \u0026\u0026 _initialized == 1),\n            \"Initializable: contract is already initialized\"\n        );\n        _initialized = 1;\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: setting the version to 255 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing \u0026\u0026 _initialized \u003c version, \"Initializable: contract is already initialized\");\n        _initialized = version;\n        _initializing = true;\n        _;\n        _initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        require(_initializing, \"Initializable: contract is not initializing\");\n        _;\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized != type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint8) {\n        return _initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _initializing;\n    }\n}\n\n// contracts/interfaces/IAgentManager.sol\n\ninterface IAgentManager {\n    /**\n     * @notice Allows Inbox to open a Dispute between a Guard and a Notary, if they are both not in Dispute already.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Guard or Notary is already in Dispute.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Allows Inbox to slash an agent, if their fraud was proven.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Domain doesn't match the saved agent domain.\n     * @param domain    Domain where the Agent is active\n     * @param agent     Address of the Agent\n     * @param prover    Address that initially provided fraud proof\n     */\n    function slashAgent(uint32 domain, address agent, address prover) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest known root of the Agent Merkle Tree.\n     */\n    function agentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns the number of opened Disputes.\n     * @dev This includes the Disputes that have been resolved already.\n     */\n    function getDisputesAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns information about the dispute with the given index.\n     * @dev Will revert if dispute with given index hasn't been opened yet.\n     * @param index             Dispute index\n     * @return guard            Address of the Guard in the Dispute\n     * @return notary           Address of the Notary in the Dispute\n     * @return slashedAgent     Address of the Agent who was slashed when Dispute was resolved\n     * @return fraudProver      Address who provided fraud proof to resolve the Dispute\n     * @return reportPayload    Raw payload with report data that led to the Dispute\n     * @return reportSignature  Guard signature for the report payload\n     */\n    function getDispute(uint256 index)\n        external\n        view\n        returns (\n            address guard,\n            address notary,\n            address slashedAgent,\n            address fraudProver,\n            bytes memory reportPayload,\n            bytes memory reportSignature\n        );\n\n    /**\n     * @notice Returns the current Dispute status of a given agent. See Structures.sol for details.\n     * @dev Every returned value will be set to zero if agent was not slashed and is not in Dispute.\n     * `rival` and `disputePtr` will be set to zero if the agent was slashed without being in Dispute.\n     * @param agent         Agent address\n     * @return flag         Flag describing the current Dispute status for the agent: None/Pending/Slashed\n     * @return rival        Address of the rival agent in the Dispute\n     * @return fraudProver  Address who provided fraud proof to resolve the Dispute\n     * @return disputePtr   Index of the opened Dispute PLUS ONE. Zero if agent is not in Dispute.\n     */\n    function disputeStatus(address agent)\n        external\n        view\n        returns (DisputeFlag flag, address rival, address fraudProver, uint256 disputePtr);\n}\n\n// contracts/interfaces/IAgentSecured.sol\n\ninterface IAgentSecured {\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * between a Guard and a Notary has been opened.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * has been resolved due to one of the agents being slashed.\n     * \u003e `rivalIndex` will be ZERO, if the slashed agent was not in the Dispute.\n     * @param slashedIndex  Index of the slashed agent in the Agent Merkle Tree\n     * @param rivalIndex    Index of the their Dispute Rival in the Agent Merkle Tree\n     */\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the address of the local AgentManager contract, which is treated as\n     * the \"source of truth\" for agent statuses.\n     */\n    function agentManager() external view returns (address);\n\n    /**\n     * @notice Returns the address of the local Inbox contract, which is treated as\n     * the \"source of truth\" for agent-signed statements.\n     * @dev Inbox passes verified agent statements to `IAgentSecured` contract.\n     */\n    function inbox() external view returns (address);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns (flag, openedAt, resolvedAt) that describes the latest status of\n     * the latest dispute for an agent with a given index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param agentIndex    Agent index in the Agent Merkle Tree\n     * @return              Latest dispute status for the given agent: (flag, openedAt, resolvedAt)\n     */\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory);\n}\n\n// contracts/libs/memory/ByteString.sol\n\n/// @dev CallData is a memory view over the payload to be used for an external call, i.e.\n/// recipient.call(callData). Its length is always (4 + 32 * N) bytes:\n/// - First 4 bytes represent the function selector.\n/// - 32 * N bytes represent N words that function arguments occupy.\ntype CallData is uint256;\n\n/// @dev Attach library functions to CallData\nusing ByteString for CallData global;\n\n/// @dev Signature is a memory view over a \"65 bytes\" array representing a ECDSA signature.\ntype Signature is uint256;\n\n/// @dev Attach library functions to Signature\nusing ByteString for Signature global;\n\nlibrary ByteString {\n    using MemViewLib for bytes;\n\n    /**\n     * @dev non-compact ECDSA signatures are enforced as of OZ 4.7.3\n     *\n     *      Signature payload memory layout\n     * [000 .. 032) r   bytes32 32 bytes\n     * [032 .. 064) s   bytes32 32 bytes\n     * [064 .. 065) v   uint8    1 byte\n     */\n    uint256 internal constant SIGNATURE_LENGTH = 65;\n    uint256 private constant OFFSET_R = 0;\n    uint256 private constant OFFSET_S = 32;\n    uint256 private constant OFFSET_V = 64;\n\n    /**\n     * @dev Calldata memory layout\n     * [000 .. 004) selector    bytes4  4 bytes\n     *      Optional: N function arguments\n     * [004 .. 036) arg1        bytes32 32 bytes\n     *      ..\n     * [AAA .. END) argN        bytes32 32 bytes\n     */\n    uint256 internal constant SELECTOR_LENGTH = 4;\n    uint256 private constant OFFSET_SELECTOR = 0;\n    uint256 private constant OFFSET_ARGUMENTS = SELECTOR_LENGTH;\n\n    // ═════════════════════════════════════════════════ SIGNATURE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the signature payload from the given values.\n     * @dev Using ByteString.formatSignature({r: r, s: s, v: v}) will make sure\n     * that params are given in the right order.\n     */\n    function formatSignature(bytes32 r, bytes32 s, uint8 v) internal pure returns (bytes memory) {\n        return abi.encodePacked(r, s, v);\n    }\n\n    /**\n     * @notice Returns a Signature view over for the given payload.\n     * @dev Will revert if the payload is not a signature.\n     */\n    function castToSignature(bytes memory payload) internal pure returns (Signature) {\n        return castToSignature(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Signature view.\n     * @dev Will revert if the memory view is not over a signature.\n     */\n    function castToSignature(MemView memView) internal pure returns (Signature) {\n        if (!isSignature(memView)) revert UnformattedSignature();\n        return Signature.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a signature\n     */\n    function isSignature(MemView memView) internal pure returns (bool) {\n        return memView.len() == SIGNATURE_LENGTH;\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Signature signature) internal pure returns (MemView) {\n        return MemView.wrap(Signature.unwrap(signature));\n    }\n\n    // ═════════════════════════════════════════════ SIGNATURE SLICING ═════════════════════════════════════════════════\n\n    /// @notice Unpacks signature payload into (r, s, v) parameters.\n    /// @dev Make sure to verify signature length with isSignature() beforehand.\n    function toRSV(Signature signature) internal pure returns (bytes32 r, bytes32 s, uint8 v) {\n        // Get the underlying memory view\n        MemView memView = unwrap(signature);\n        r = memView.index({index_: OFFSET_R, bytes_: 32});\n        s = memView.index({index_: OFFSET_S, bytes_: 32});\n        // Can be safely casted to uint8, since we index a single byte\n        v = uint8(memView.indexUint({index_: OFFSET_V, bytes_: 1}));\n    }\n\n    // ═════════════════════════════════════════════════ CALLDATA ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the calldata with the modified arguments:\n     * the existing arguments are prepended with the arguments from the prefix.\n     * @dev Given:\n     *  - `calldata = abi.encodeWithSelector(foo.selector, d, e);`\n     *  - `prefix = abi.encode(a, b, c);`\n     *  - `a`, `b`, `c` are arguments of static type (i.e. not dynamically sized ones)\n     *      Then:\n     *  - Function will return abi.encodeWithSelector(foo.selector, a, c, c, d, e)\n     *  - Returned calldata will trigger `foo(a, b, c, d, e)` when used for a contract call.\n     * Note: for clarification as to what types are considered static, see\n     * https://docs.soliditylang.org/en/latest/abi-spec.html#formal-specification-of-the-encoding\n     * @param callData  Calldata that needs to be modified\n     * @param prefix    ABI-encoded arguments to use as the first arguments in the new calldata\n     * @return Modified calldata having prefix as the first arguments.\n     */\n    function addPrefix(CallData callData, bytes memory prefix) internal view returns (bytes memory) {\n        // Prefix should occupy a whole amount of words in memory\n        if (!_fullWords(prefix.length)) revert UnformattedCallDataPrefix();\n        MemView[] memory views = new MemView[](3);\n        // Use payload's function selector\n        views[0] = abi.encodePacked(callData.callSelector()).ref();\n        // Use prefix as the first arguments\n        views[1] = prefix.ref();\n        // Use payload's remaining arguments\n        views[2] = callData.arguments();\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a CallData view over for the given payload.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(bytes memory payload) internal pure returns (CallData) {\n        return castToCallData(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a CallData view.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(MemView memView) internal pure returns (CallData) {\n        if (!isCallData(memView)) revert UnformattedCallData();\n        return CallData.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a valid calldata, i.e.\n     * a function selector, followed by arbitrary amount of arguments.\n     */\n    function isCallData(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Calldata should at least have a function selector\n        if (length \u003c SELECTOR_LENGTH) return false;\n        // The remainder of the calldata should be exactly N memory words (N \u003e= 0)\n        return _fullWords(length - SELECTOR_LENGTH);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(CallData callData) internal pure returns (MemView) {\n        return MemView.wrap(CallData.unwrap(callData));\n    }\n\n    /// @notice Returns callData's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(CallData callData) internal pure returns (bytes32) {\n        return callData.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ CALLDATA SLICING ══════════════════════════════════════════════════\n\n    /**\n     * @notice Returns amount of memory words (32 byte chunks) the function arguments\n     * occupy in the calldata.\n     * @dev This might differ from amount of arguments supplied, if any of the arguments\n     * occupies more than one memory slot. It is true, however, that argument part of the payload\n     * occupies exactly N words, even for dynamic types like `bytes`\n     */\n    function argumentWords(CallData callData) internal pure returns (uint256) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        // Equivalent of (length - SELECTOR_LENGTH) / 32\n        return (memView.len() - SELECTOR_LENGTH) \u003e\u003e 5;\n    }\n\n    /// @notice Returns selector for the provided calldata.\n    function callSelector(CallData callData) internal pure returns (bytes4) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return bytes4(memView.index({index_: OFFSET_SELECTOR, bytes_: SELECTOR_LENGTH}));\n    }\n\n    /// @notice Returns abi encoded arguments for the provided calldata.\n    function arguments(CallData callData) internal pure returns (MemView) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return memView.sliceFrom({index_: OFFSET_ARGUMENTS});\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if length is full amount of memory words (32 bytes).\n    function _fullWords(uint256 length) internal pure returns (bool) {\n        // The equivalent of length % 32 == 0\n        return length \u0026 31 == 0;\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n    function __Context_init() internal onlyInitializing {\n    }\n\n    function __Context_init_unchained() internal onlyInitializing {\n    }\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[50] private __gap;\n}\n\n// contracts/libs/merkle/MerkleTree.sol\n\n/// `BaseTree` is a struct representing incremental merkle tree.\n/// - Contains only the current branch.\n/// - The number of inserted leaves is stored externally, and is later supplied for tree operations.\n/// - Has a fixed height of `ORIGIN_TREE_HEIGHT`.\n/// - Can store up to `2 ** ORIGIN_TREE_HEIGHT - 1` leaves.\n/// \u003e Note: the hash function for the tree `H(x, y)` is defined as:\n/// \u003e - `H(0,0) = 0`\n/// \u003e - `H(x,y) = keccak256(x, y), when (x != 0 || y != 0)`\n/// ## Invariant for leafs\n/// - The leftmost empty leaf has `index == count`, where `count` is the amount of the inserted leafs so far.\n/// - Value for any empty leaf or node is bytes32(0).\n/// ## Invariant for current branch\n/// `branch[i]` is always the value of a node on the i-th level.\n/// Levels are numbered from leafs to root: `0 .. ORIGIN_TREE_HEIGHT`.\n/// `branch[i]` stores the value for the node, such that:\n//  - The node is a \"left child\" (e.g. has an even index).\n/// - The node must have two non-empty children.\n/// - Out of all level's \"left child\" nodes with \"non-empty children\",\n/// the one with the biggest index (the rightmost one) is stored as `branch[i]`.\n/// \u003e __`branch` could be used to form a proof of inclusion for the first empty leaf (`index == count`).__\n/// _Here is how:_\n/// - Let's walk along the path from the \"first empty leaf\" to the root.\n/// - i-th bit of the \"first empty leaf\" index (which is equal to `count`) determines if the path's node\n/// for this i-th level is a \"left child\" or a \"right child\".\n/// - i-th bit in `count` is 0 → we are the left child on this level → sibling is the right child\n/// that does not exist yet → `proof[i] = bytes32(0)`.\n/// - i-th bit in `count` is 1 → we are the right child on this level → sibling is the left child\n/// sibling is the rightmost \"left child\" node on the level → `proof[i] = branch[i]`.\n/// \u003e Therefore `proof[i] = (count \u0026 (1 \u003c\u003c i)) == 0 ? bytes32(0) : branch[i])`\nstruct BaseTree {\n    bytes32[ORIGIN_TREE_HEIGHT] branch;\n}\n\nusing MerkleTree for BaseTree global;\n\n/// `HistoricalTree` is an incremental merkle tree keeping track of its historical merkle roots.\n/// \u003e - `roots[N]` is the root of the tree after `N` leafs were inserted\n/// \u003e - `roots[0] == bytes32(0)`\n/// @param tree     Incremental merkle tree\n/// @param roots    Historical merkle roots of the tree\nstruct HistoricalTree {\n    BaseTree tree;\n    bytes32[] roots;\n}\n\nusing MerkleTree for HistoricalTree global;\n\n/// `DynamicTree` is a struct representing a Merkle Tree with `2**AGENT_TREE_HEIGHT` leaves.\n/// - A single operation is available: update value for leaf with an arbitrary index (which might be a non-empty leaf).\n/// - This is done by requesting the proof of inclusion for the old value, which is used to both\n/// verify the old value, and calculate the new root.\n/// \u003e Based on Original idea from [ER forum post](https://ethresear.ch/t/efficient-on-chain-dynamic-merkle-tree/11054).\nstruct DynamicTree {\n    bytes32 root;\n}\n\nusing MerkleTree for DynamicTree global;\n\n/// MerkleTree is work based on Nomad's Merkle.sol, which is used under MIT OR Apache-2.0\n/// [link](https://github.com/nomad-xyz/monorepo/blob/main/packages/contracts-core/contracts/libs/Merkle.sol).\n/// With the following changes:\n/// - Adapted for Solidity 0.8.x.\n/// - Amount of tree leaves stored externally.\n/// - Added thorough documentation.\n/// - `H(0,0) = 0` optimization from [ER forum post](https://ethresear.ch/t/optimizing-sparse-merkle-trees/3751/6).\n/// \u003e Nomad's Merkle.sol is work based on eth2 deposit contract, which is used under CC0-1.0\n///[link](https://github.com/ethereum/deposit_contract/blob/dev/deposit_contract/contracts/validator_registration.v.py).\n/// With the following changes:\n/// \u003e - Implemented in Solidity 0.7.6 (eth2 deposit contract implemented in Vyper).\n/// \u003e - `H() = keccak256()` is used as the hashing function instead of `sha256()`.\nlibrary MerkleTree {\n    /// @dev For root calculation we need at least one empty leaf, thus the minus one in the formula.\n    uint256 internal constant MAX_LEAVES = 2 ** ORIGIN_TREE_HEIGHT - 1;\n\n    // ═════════════════════════════════════════════════ BASE TREE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Inserts `node` into merkle tree\n     * @dev Reverts if tree is full\n     * @param newCount  Amount of inserted leaves in the tree after the insertion (i.e. current + 1)\n     * @param node      Element to insert into tree\n     */\n    function insertBase(BaseTree storage tree, uint256 newCount, bytes32 node) internal {\n        if (newCount \u003e MAX_LEAVES) revert MerkleTreeFull();\n        // We go up the tree following the branch from the empty leaf AFTER the just inserted one.\n        // We stop when we find the first \"right child\" node.\n        // Its sibling is now the rightmost \"left child\" node that has two non-empty children.\n        // Therefore we need to update `tree.branch` value on this level.\n        // One could see that `tree.branch` value on lower and higher levels remain unchanged.\n\n        // Loop invariant: `node` is the current level's value for the branch from JUST INSERTED leaf\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            if ((newCount \u0026 1) == 1) {\n                // Found the first \"right child\" node on the branch from EMPTY leaf\n                // `node` is the value for node on branch from JUST INSERTED leaf\n                // Which in this case is the \"left child\".\n                // We update tree.branch and exit\n                tree.branch[i] = node;\n                return;\n            }\n            // On the branch from EMPTY leaf this is still a \"left child\".\n            // Meaning on branch from JUST INSERTED leaf, `node` is a right child.\n            // We compute value for `node` parent using `tree.branch` invariant:\n            // This is the rightmost \"left child\" node, which would be sibling of `node`.\n            node = MerkleMath.getParent(tree.branch[i], node);\n            // Get the parent index, and go to the next tree level\n            newCount \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n        // As the loop should always end prematurely with the `return` statement,\n        // this code should be unreachable. We assert `false` just to be safe.\n        assert(false);\n    }\n\n    /**\n     * @notice Calculates and returns current root of the merkle tree.\n     * @param count     Current amount of inserted leaves in the tree\n     * @return current  Calculated root of `tree`\n     */\n    function rootBase(BaseTree storage tree, uint256 count) internal view returns (bytes32 current) {\n        // To calculate the root we follow the branch of first EMPTY leaf (index == count)\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            // Check if we are the left or the right child on the current level\n            if ((count \u0026 1) == 1) {\n                // We are the right child. Our sibling is the \"rightmost\" \"left-child\" node\n                // that has two non-empty children → sibling is `tree.branch[i]`\n                current = MerkleMath.getParent(tree.branch[i], current);\n            } else {\n                // We are the left child. Our sibling does not exist yet → sibling is EMPTY\n                current = MerkleMath.getParent(current, bytes32(0));\n            }\n            // Get the parent index, and go to the next tree level\n            count \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    // ══════════════════════════════════════════════ HISTORICAL TREE ══════════════════════════════════════════════════\n\n    /// @notice Initializes the historical roots for the tree by inserting an empty root.\n    // solhint-disable-next-line ordering\n    function initializeRoots(HistoricalTree storage tree) internal returns (bytes32 savedRoot) {\n        // This should only be called once, when the contract is initialized\n        assert(tree.roots.length == 0);\n        // Save root for empty merkle tree: bytes32(0)\n        tree.roots.push(savedRoot);\n    }\n\n    /// @notice Inserts a new leaf into the merkle tree.\n    /// @dev Reverts if tree is full.\n    /// @param node         Element to insert into tree\n    /// @return newRoot     Merkle root after the leaf was inserted\n    function insert(HistoricalTree storage tree, bytes32 node) internal returns (bytes32 newRoot) {\n        // Tree count after the new leaf will be inserted (we store roots[0] as root of empty tree)\n        uint256 newCount = tree.roots.length;\n        tree.tree.insertBase(newCount, node);\n        // Save the new root\n        newRoot = tree.tree.rootBase(newCount);\n        tree.roots.push(newRoot);\n    }\n\n    /// @notice Returns the historical root of the merkle tree.\n    /// @dev Reverts if not enough leafs have been inserted.\n    /// @param count            Amount of leafs in the tree at some point of time\n    /// @return historicalRoot  Merkle root after `count` leafs were inserted\n    function root(HistoricalTree storage tree, uint256 count) internal view returns (bytes32 historicalRoot) {\n        if (count \u003e= tree.roots.length) revert NotEnoughLeafs();\n        return tree.roots[count];\n    }\n\n    // ═══════════════════════════════════════════════ DYNAMIC TREE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Updates the value for the leaf with the given index in the Dynamic Merkle Tree.\n     * @dev Will revert if incorrect proof of inclusion for old value is supplied.\n     * @param tree          Dynamic merkle tree\n     * @param index         Index of the leaf to update\n     * @param oldValue      Previous value of the leaf\n     * @param branch        Proof of inclusion of previous value into the tree\n     * @param newValue      New leaf value to assign\n     * @return newRoot      New value for the Merkle Root after the leaf is updated\n     */\n    function update(\n        DynamicTree storage tree,\n        uint256 index,\n        bytes32 oldValue,\n        bytes32[] memory branch,\n        bytes32 newValue\n    ) internal returns (bytes32 newRoot) {\n        // Check that the old value + proof result in a correct root\n        if (MerkleMath.proofRoot(index, oldValue, branch, AGENT_TREE_HEIGHT) != tree.root) {\n            revert LeafNotProven();\n        }\n        // New root is new value + the same proof (values for sibling nodes are not updated)\n        newRoot = MerkleMath.proofRoot(index, newValue, branch, AGENT_TREE_HEIGHT);\n        // Write the new root\n        tree.root = newRoot;\n    }\n}\n\n// contracts/libs/stack/Tips.sol\n\n/// Tips is encoded data with \"tips paid for sending a base message\".\n/// Note: even though uint256 is also an underlying type for MemView, Tips is stored ON STACK.\ntype Tips is uint256;\n\nusing TipsLib for Tips global;\n\n/// # Tips\n/// Library for formatting _the tips part_ of _the base messages_.\n///\n/// ## How the tips are awarded\n/// Tips are paid for sending a base message, and are split across all the agents that\n/// made the message execution on destination chain possible.\n/// ### Summit tips\n/// Split between:\n///     - Guard posting a snapshot with state ST_G for the origin chain.\n///     - Notary posting a snapshot SN_N using ST_G. This creates attestation A.\n///     - Notary posting a message receipt after it is executed on destination chain.\n/// ### Attestation tips\n/// Paid to:\n///     - Notary posting attestation A to destination chain.\n/// ### Execution tips\n/// Paid to:\n///     - First executor performing a valid execution attempt (correct proofs, optimistic period over),\n///      using attestation A to prove message inclusion on origin chain, whether the recipient reverted or not.\n/// ### Delivery tips.\n/// Paid to:\n///     - Executor who successfully executed the message on destination chain.\n///\n/// ## Tips encoding\n/// - Tips occupy a single storage word, and thus are stored on stack instead of being stored in memory.\n/// - The actual tip values should be determined by multiplying stored values by divided by TIPS_MULTIPLIER=2**32.\n/// - Tips are packed into a single word of storage, while allowing real values up to ~8*10**28 for every tip category.\n/// \u003e The only downside is that the \"real tip values\" are now multiplies of ~4*10**9, which should be fine even for\n/// the chains with the most expensive gas currency.\n/// # Tips stack layout (from highest bits to lowest)\n///\n/// | Position   | Field          | Type   | Bytes | Description                                                |\n/// | ---------- | -------------- | ------ | ----- | ---------------------------------------------------------- |\n/// | (032..024] | summitTip      | uint64 | 8     | Tip for agents interacting with Summit contract            |\n/// | (024..016] | attestationTip | uint64 | 8     | Tip for Notary posting attestation to Destination contract |\n/// | (016..008] | executionTip   | uint64 | 8     | Tip for valid execution attempt on destination chain       |\n/// | (008..000] | deliveryTip    | uint64 | 8     | Tip for successful message delivery on destination chain   |\n\nlibrary TipsLib {\n    using SafeCast for uint256;\n\n    /// @dev Amount of bits to shift to summitTip field\n    uint256 private constant SHIFT_SUMMIT_TIP = 24 * 8;\n    /// @dev Amount of bits to shift to attestationTip field\n    uint256 private constant SHIFT_ATTESTATION_TIP = 16 * 8;\n    /// @dev Amount of bits to shift to executionTip field\n    uint256 private constant SHIFT_EXECUTION_TIP = 8 * 8;\n\n    // ═══════════════════════════════════════════════════ TIPS ════════════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips with the given fields\n    /// @param summitTip_        Tip for agents interacting with Summit contract, divided by TIPS_MULTIPLIER\n    /// @param attestationTip_   Tip for Notary posting attestation to Destination contract, divided by TIPS_MULTIPLIER\n    /// @param executionTip_     Tip for valid execution attempt on destination chain, divided by TIPS_MULTIPLIER\n    /// @param deliveryTip_      Tip for successful message delivery on destination chain, divided by TIPS_MULTIPLIER\n    function encodeTips(uint64 summitTip_, uint64 attestationTip_, uint64 executionTip_, uint64 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // forgefmt: disable-next-item\n        return Tips.wrap(\n            uint256(summitTip_) \u003c\u003c SHIFT_SUMMIT_TIP |\n            uint256(attestationTip_) \u003c\u003c SHIFT_ATTESTATION_TIP |\n            uint256(executionTip_) \u003c\u003c SHIFT_EXECUTION_TIP |\n            uint256(deliveryTip_)\n        );\n    }\n\n    /// @notice Convenience function to encode tips with uint256 values.\n    function encodeTips256(uint256 summitTip_, uint256 attestationTip_, uint256 executionTip_, uint256 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // In practice, the tips amounts are not supposed to be higher than 2**96, and with 32 bits of granularity\n        // using uint64 is enough to store the values. However, we still check for overflow just in case.\n        // TODO: consider using Number type to store the tips values.\n        return encodeTips({\n            summitTip_: (summitTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            attestationTip_: (attestationTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            executionTip_: (executionTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            deliveryTip_: (deliveryTip_ \u003e\u003e TIPS_GRANULARITY).toUint64()\n        });\n    }\n\n    /// @notice Wraps the padded encoded tips into a Tips-typed value.\n    /// @dev There is no actual padding here, as the underlying type is already uint256,\n    /// but we include this function for consistency and to be future-proof, if tips will eventually use anything\n    /// smaller than uint256.\n    function wrapPadded(uint256 paddedTips) internal pure returns (Tips) {\n        return Tips.wrap(paddedTips);\n    }\n\n    /**\n     * @notice Returns a formatted Tips payload specifying empty tips.\n     * @return Formatted tips\n     */\n    function emptyTips() internal pure returns (Tips) {\n        return Tips.wrap(0);\n    }\n\n    /// @notice Returns tips's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Tips tips) internal pure returns (bytes32 hashedTips) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store tips in scratch space\n            mstore(0, tips)\n            // Compute hash of tips padded to 32 bytes\n            hashedTips := keccak256(0, 32)\n        }\n    }\n\n    // ═══════════════════════════════════════════════ TIPS SLICING ════════════════════════════════════════════════════\n\n    /// @notice Returns summitTip field\n    function summitTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_SUMMIT_TIP);\n    }\n\n    /// @notice Returns attestationTip field\n    function attestationTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_ATTESTATION_TIP);\n    }\n\n    /// @notice Returns executionTip field\n    function executionTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_EXECUTION_TIP);\n    }\n\n    /// @notice Returns deliveryTip field\n    function deliveryTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips));\n    }\n\n    // ════════════════════════════════════════════════ TIPS VALUE ═════════════════════════════════════════════════════\n\n    /// @notice Returns total value of the tips payload.\n    /// This is the sum of the encoded values, scaled up by TIPS_MULTIPLIER\n    function value(Tips tips) internal pure returns (uint256 value_) {\n        value_ = uint256(tips.summitTip()) + tips.attestationTip() + tips.executionTip() + tips.deliveryTip();\n        value_ \u003c\u003c= TIPS_GRANULARITY;\n    }\n\n    /// @notice Increases the delivery tip to match the new value.\n    function matchValue(Tips tips, uint256 newValue) internal pure returns (Tips newTips) {\n        uint256 oldValue = tips.value();\n        if (newValue \u003c oldValue) revert TipsValueTooLow();\n        // We want to increase the delivery tip, while keeping the other tips the same\n        unchecked {\n            uint256 delta = (newValue - oldValue) \u003e\u003e TIPS_GRANULARITY;\n            // `delta` fits into uint224, as TIPS_GRANULARITY is 32, so this never overflows uint256.\n            // In practice, this will never overflow uint64 as well, but we still check it just in case.\n            if (delta + tips.deliveryTip() \u003e type(uint64).max) revert TipsOverflow();\n            // Delivery tips occupy lowest 8 bytes, so we can just add delta to the tips value\n            // to effectively increase the delivery tip (knowing that delta fits into uint64).\n            newTips = Tips.wrap(Tips.unwrap(tips) + delta);\n        }\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    function __Ownable_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable_init_unchained() internal onlyInitializing {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n    function __Ownable2Step_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable2Step_init_unchained() internal onlyInitializing {\n    }\n    address private _pendingOwner;\n\n    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Returns the address of the pending owner.\n     */\n    function pendingOwner() public view virtual returns (address) {\n        return _pendingOwner;\n    }\n\n    /**\n     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual override onlyOwner {\n        _pendingOwner = newOwner;\n        emit OwnershipTransferStarted(owner(), newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual override {\n        delete _pendingOwner;\n        super._transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev The new owner accepts the ownership transfer.\n     */\n    function acceptOwnership() public virtual {\n        address sender = _msgSender();\n        require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n        _transferOwnership(sender);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// contracts/libs/memory/State.sol\n\n/// State is a memory view over a formatted state payload.\ntype State is uint256;\n\nusing StateLib for State global;\n\n/// # State\n/// State structure represents the state of Origin contract at some point of time.\n/// - State is structured in a way to track the updates of the Origin Merkle Tree.\n/// - State includes root of the Origin Merkle Tree, origin domain and some additional metadata.\n/// ## Origin Merkle Tree\n/// Hash of every sent message is inserted in the Origin Merkle Tree, which changes\n/// the value of Origin Merkle Root (which is the root for the mentioned tree).\n/// - Origin has a single Merkle Tree for all messages, regardless of their destination domain.\n/// - This leads to Origin state being updated if and only if a message was sent in a block.\n/// - Origin contract is a \"source of truth\" for states: a state is considered \"valid\" in its Origin,\n/// if it matches the state of the Origin contract after the N-th (nonce) message was sent.\n///\n/// # Memory layout of State fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                    |\n/// | ---------- | ----------- | ------- | ----- | ------------------------------ |\n/// | [000..032) | root        | bytes32 | 32    | Root of the Origin Merkle Tree |\n/// | [032..036) | origin      | uint32  | 4     | Domain where Origin is located |\n/// | [036..040) | nonce       | uint32  | 4     | Amount of sent messages        |\n/// | [040..045) | blockNumber | uint40  | 5     | Block of last sent message     |\n/// | [045..050) | timestamp   | uint40  | 5     | Time of last sent message      |\n/// | [050..062) | gasData     | uint96  | 12    | Gas data for the chain         |\n///\n/// @dev State could be used to form a Snapshot to be signed by a Guard or a Notary.\nlibrary StateLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_ROOT = 0;\n    uint256 private constant OFFSET_ORIGIN = 32;\n    uint256 private constant OFFSET_NONCE = 36;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 40;\n    uint256 private constant OFFSET_TIMESTAMP = 45;\n    uint256 private constant OFFSET_GAS_DATA = 50;\n\n    // ═══════════════════════════════════════════════════ STATE ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted State payload with provided fields\n     * @param root_         New merkle root\n     * @param origin_       Domain of Origin's chain\n     * @param nonce_        Nonce of the merkle root\n     * @param blockNumber_  Block number when root was saved in Origin\n     * @param timestamp_    Block timestamp when root was saved in Origin\n     * @param gasData_      Gas data for the chain\n     * @return Formatted state\n     */\n    function formatState(\n        bytes32 root_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_,\n        GasData gasData_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(root_, origin_, nonce_, blockNumber_, timestamp_, gasData_);\n    }\n\n    /**\n     * @notice Returns a State view over the given payload.\n     * @dev Will revert if the payload is not a state.\n     */\n    function castToState(bytes memory payload) internal pure returns (State) {\n        return castToState(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a State view.\n     * @dev Will revert if the memory view is not over a state.\n     */\n    function castToState(MemView memView) internal pure returns (State) {\n        if (!isState(memView)) revert UnformattedState();\n        return State.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted State.\n    function isState(MemView memView) internal pure returns (bool) {\n        return memView.len() == STATE_LENGTH;\n    }\n\n    /// @notice Returns the hash of a State, that could be later signed by a Guard to signal\n    /// that the state is invalid.\n    function hashInvalid(State state) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(stateInvalidSalt, keccak(state))\n        return state.unwrap().keccakSalted(STATE_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(State state) internal pure returns (MemView) {\n        return MemView.wrap(State.unwrap(state));\n    }\n\n    /// @notice Compares two State structures.\n    function equals(State a, State b) internal pure returns (bool) {\n        // Length of a State payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═══════════════════════════════════════════════ STATE HASHING ═══════════════════════════════════════════════════\n\n    /// @notice Returns the hash of the State.\n    /// @dev We are using the Merkle Root of a tree with two leafs (see below) as state hash.\n    function leaf(State state) internal pure returns (bytes32) {\n        (bytes32 leftLeaf_, bytes32 rightLeaf_) = state.subLeafs();\n        // Final hash is the parent of these leafs\n        return keccak256(bytes.concat(leftLeaf_, rightLeaf_));\n    }\n\n    /// @notice Returns \"sub-leafs\" of the State. Hash of these \"sub leafs\" is going to be used\n    /// as a \"state leaf\" in the \"Snapshot Merkle Tree\".\n    /// This enables proving that leftLeaf = (root, origin) was a part of the \"Snapshot Merkle Tree\",\n    /// by combining `rightLeaf` with the remainder of the \"Snapshot Merkle Proof\".\n    function subLeafs(State state) internal pure returns (bytes32 leftLeaf_, bytes32 rightLeaf_) {\n        MemView memView = state.unwrap();\n        // Left leaf is (root, origin)\n        leftLeaf_ = memView.prefix({len_: OFFSET_NONCE}).keccak();\n        // Right leaf is (metadata), or (nonce, blockNumber, timestamp)\n        rightLeaf_ = memView.sliceFrom({index_: OFFSET_NONCE}).keccak();\n    }\n\n    /// @notice Returns the left \"sub-leaf\" of the State.\n    function leftLeaf(bytes32 root_, uint32 origin_) internal pure returns (bytes32) {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(root_, origin_));\n    }\n\n    /// @notice Returns the right \"sub-leaf\" of the State.\n    function rightLeaf(uint32 nonce_, uint40 blockNumber_, uint40 timestamp_, GasData gasData_)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(nonce_, blockNumber_, timestamp_, gasData_));\n    }\n\n    // ═══════════════════════════════════════════════ STATE SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns a historical Merkle root from the Origin contract.\n    function root(State state) internal pure returns (bytes32) {\n        return state.unwrap().index({index_: OFFSET_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns domain of chain where the Origin contract is deployed.\n    function origin(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns nonce of Origin contract at the time, when `root` was the Merkle root.\n    function nonce(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when `root` was saved in Origin.\n    function blockNumber(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when `root` was saved in Origin.\n    /// @dev This is the timestamp according to the origin chain.\n    function timestamp(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n\n    /// @notice Returns gas data for the chain.\n    function gasData(State state) internal pure returns (GasData) {\n        return GasDataLib.wrapGasData(state.unwrap().indexUint({index_: OFFSET_GAS_DATA, bytes_: GAS_DATA_LENGTH}));\n    }\n}\n\n// contracts/libs/memory/BaseMessage.sol\n\n/// BaseMessage is a memory view over the base message supported by Origin-Destination\ntype BaseMessage is uint256;\n\nusing BaseMessageLib for BaseMessage global;\n\n/// BaseMessage structure represents a base message sent via the Origin-Destination contracts.\n/// - It only contains data relevant to the base message, the rest of data is encoded in the message header.\n/// - `sender` and `recipient` for EVM chains are EVM addresses casted to bytes32, while preserving left-alignment.\n/// - `tips` and `request` parameters are specified by a message sender\n/// \u003e Origin will calculate minimum tips for given request and content length, and will reject messages with tips\n/// lower than that.\n///\n/// # Memory layout of BaseMessage fields\n///\n/// | Position   | Field     | Type    | Bytes | Description                            |\n/// | ---------- | --------- | ------- | ----- | -------------------------------------- |\n/// | [000..032) | tips      | uint256 | 32    | Encoded tips paid on origin chain      |\n/// | [032..064) | sender    | bytes32 | 32    | Sender address on origin chain         |\n/// | [064..096) | recipient | bytes32 | 32    | Recipient address on destination chain |\n/// | [096..116) | request   | uint160 | 20    | Encoded request for message execution  |\n/// | [104..AAA) | content   | bytes   | ??    | Content to be passed to recipient      |\nlibrary BaseMessageLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_TIPS = 0;\n    uint256 private constant OFFSET_SENDER = 32;\n    uint256 private constant OFFSET_RECIPIENT = 64;\n    uint256 private constant OFFSET_REQUEST = OFFSET_RECIPIENT + TIPS_LENGTH;\n    uint256 private constant OFFSET_CONTENT = OFFSET_REQUEST + REQUEST_LENGTH;\n\n    // ═══════════════════════════════════════════════ BASE MESSAGE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted BaseMessage payload with provided fields.\n     * @param tips_         Encoded tips information\n     * @param sender_       Sender address on origin chain\n     * @param recipient_    Recipient address on destination chain\n     * @param request_      Encoded request for message execution\n     * @param content_      Raw content to be passed to recipient on destination chain\n     * @return Formatted base message\n     */\n    function formatBaseMessage(Tips tips_, bytes32 sender_, bytes32 recipient_, Request request_, bytes memory content_)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return abi.encodePacked(tips_, sender_, recipient_, request_, content_);\n    }\n\n    /**\n     * @notice Returns a BaseMessage view over the given payload.\n     * @dev Will revert if the payload is not a base message.\n     */\n    function castToBaseMessage(bytes memory payload) internal pure returns (BaseMessage) {\n        return castToBaseMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a BaseMessage view.\n     * @dev Will revert if the memory view is not over a base message payload.\n     */\n    function castToBaseMessage(MemView memView) internal pure returns (BaseMessage) {\n        if (!isBaseMessage(memView)) revert UnformattedBaseMessage();\n        return BaseMessage.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted BaseMessage.\n    function isBaseMessage(MemView memView) internal pure returns (bool) {\n        // Check if sender, recipient, tips fields exist\n        return (memView.len() \u003e= OFFSET_CONTENT);\n        // Content could be empty, so we don't check that\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(BaseMessage baseMessage) internal pure returns (MemView) {\n        return MemView.wrap(BaseMessage.unwrap(baseMessage));\n    }\n\n    /// @notice Returns baseMessage's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        // We hash \"tips\" and \"everything but tips\" to make tips proofs easier to verify\n        return MerkleMath.getParent(baseMessage.tips().leaf(), baseMessage.bodyLeaf());\n    }\n\n    /// @notice Returns hash for the \"everything but tips\" part of the base message.\n    function bodyLeaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_SENDER}).keccak();\n    }\n\n    // ═══════════════════════════════════════════ BASE MESSAGE SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips paid on origin chain.\n    function tips(BaseMessage baseMessage) internal pure returns (Tips) {\n        return TipsLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_TIPS, bytes_: TIPS_LENGTH})));\n    }\n\n    /// @notice Returns sender address on origin chain.\n    function sender(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_SENDER, bytes_: 32});\n    }\n\n    /// @notice Returns recipient address on destination chain.\n    function recipient(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_RECIPIENT, bytes_: 32});\n    }\n\n    /// @notice Returns an encoded request for message execution on destination chain.\n    function request(BaseMessage baseMessage) internal pure returns (Request) {\n        return RequestLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_REQUEST, bytes_: REQUEST_LENGTH})));\n    }\n\n    /// @notice Returns an untyped memory view over the content to be passed to recipient.\n    function content(BaseMessage baseMessage) internal pure returns (MemView) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_CONTENT});\n    }\n}\n\n// contracts/base/MessagingBase.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for all messaging contracts.\n * - Provides context on the local chain's domain.\n * - Provides ownership functionality.\n * - Will be providing pausing functionality when it is implemented.\n */\nabstract contract MessagingBase is MultiCallable, Versioned, Ownable2StepUpgradeable {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @notice Domain of the local chain, set once upon contract creation\n    uint32 public immutable localDomain;\n    // @notice Domain of the Synapse chain, set once upon contract creation\n    uint32 public immutable synapseDomain;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev gap for upgrade safety\n    uint256[50] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    constructor(string memory version_, uint32 synapseDomain_) Versioned(version_) {\n        localDomain = ChainContext.chainId();\n        synapseDomain = synapseDomain_;\n    }\n\n    // TODO: Implement pausing\n\n    /**\n     * @dev Should be impossible to renounce ownership;\n     * we override OpenZeppelin OwnableUpgradeable's\n     * implementation of renounceOwnership to make it a no-op\n     */\n    function renounceOwnership() public override onlyOwner {} //solhint-disable-line no-empty-blocks\n}\n\n// contracts/libs/memory/Message.sol\n\n/// Message is a memory over over a formatted message payload.\ntype Message is uint256;\n\nusing MessageLib for Message global;\n\n/// Library for formatting the various messages supported by Origin and Destination.\n///\n/// # Message memory layout\n///\n/// | Position   | Field  | Type    | Bytes | Description                                             |\n/// | ---------- | ------ | ------- | ----- | ------------------------------------------------------- |\n/// | [000..017) | header | uint136 | 17    | Encoded general routing information for the message     |\n/// | [017..AAA) | body   | bytes   | ??    | Formatted payload (according to flag) with message body |\nlibrary MessageLib {\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MemViewLib for bytes;\n    using HeaderLib for MemView;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_HEADER = 0;\n    uint256 private constant OFFSET_BODY = OFFSET_HEADER + HEADER_LENGTH;\n\n    // ══════════════════════════════════════════════════ MESSAGE ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns formatted message with provided fields.\n     * @param header_   Encoded general routing information for the message\n     * @param body_     Formatted payload (according to flag) with message body\n     * @return Formatted message\n     */\n    function formatMessage(Header header_, bytes memory body_) internal pure returns (bytes memory) {\n        return abi.encodePacked(header_, body_);\n    }\n\n    /**\n     * @notice Returns a Message view over for the given payload.\n     * @dev Will revert if the payload is not a message payload.\n     */\n    function castToMessage(bytes memory payload) internal pure returns (Message) {\n        return castToMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Message view.\n     * @dev Will revert if the memory view is not over a message payload.\n     */\n    function castToMessage(MemView memView) internal pure returns (Message) {\n        if (!isMessage(memView)) revert UnformattedMessage();\n        return Message.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Message.\n     */\n    function isMessage(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Check if headers exist in the payload\n        if (length \u003c OFFSET_BODY) return false;\n        // Check that Header is valid\n        uint256 paddedHeader = _header(memView);\n        if (!HeaderLib.isHeader(paddedHeader)) return false;\n        // Check that body is formatted according to the flag\n        // Only Base/Manager message flags exist\n        if (HeaderLib.wrapPadded(paddedHeader).flag() == MessageFlag.Base) {\n            // Check if body is a formatted base message\n            return _body(memView).isBaseMessage();\n        } else {\n            // Check if body is a formatted calldata for AgentManager call\n            return _body(memView).isCallData();\n        }\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Message message) internal pure returns (MemView) {\n        return MemView.wrap(Message.unwrap(message));\n    }\n\n    /// @notice Returns message's hash: a leaf to be inserted in the Merkle tree.\n    function leaf(Message message) internal pure returns (bytes32) {\n        // We hash header and body separately to make message proofs easier to verify\n        Header header_ = message.header();\n        // Only Base/Manager message flags exist\n        if (header_.flag() == MessageFlag.Base) {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToBaseMessage().leaf());\n        } else {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToCallData().leaf());\n        }\n    }\n\n    // ══════════════════════════════════════════════ MESSAGE SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns message's encoded header field.\n    function header(Message message) internal pure returns (Header) {\n        return HeaderLib.wrapPadded((message.unwrap().indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH})));\n    }\n\n    /// @notice Returns message's body field as an untyped memory view.\n    function body(Message message) internal pure returns (MemView) {\n        MemView memView = message.unwrap();\n        return _body(memView);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns message's padded header without checking that it is a valid header.\n    function _header(MemView memView) private pure returns (uint256) {\n        return memView.indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH});\n    }\n\n    /// @dev Returns an untyped memory view over the body field without checking\n    /// if the whole payload or the body are properly formatted.\n    function _body(MemView memView) private pure returns (MemView) {\n        return memView.sliceFrom({index_: OFFSET_BODY});\n    }\n}\n\n// contracts/base/AgentSecured.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for messaging contracts that are secured by the agent manager.\n * `AgentSecured` relies on `AgentManager` to provide the following functionality:\n * - Keep track of agents and their statuses.\n * - Pass agent-signed statements that were verified by the agent manager.\n * - These statements are considered valid indefinitely, unless the agent is disputed.\n * - Disputes are opened and resolved by the agent manager.\n * \u003e `AgentSecured` implementation should never use statements signed by agents that are disputed.\n */\nabstract contract AgentSecured is MessagingBase, IAgentSecured {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    address public immutable agentManager;\n\n    /// @inheritdoc IAgentSecured\n    address public immutable inbox;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    // (agent index =\u003e their dispute status: flag, openedAt, resolvedAt)\n    mapping(uint32 =\u003e DisputeStatus) internal _disputes;\n\n    /// @dev gap for upgrade safety\n    uint256[49] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    modifier onlyAgentManager() {\n        if (msg.sender != agentManager) revert CallerNotAgentManager();\n        _;\n    }\n\n    modifier onlyInbox() {\n        if (msg.sender != inbox) revert CallerNotInbox();\n        _;\n    }\n\n    constructor(string memory version_, uint32 synapseDomain_, address agentManager_, address inbox_)\n        MessagingBase(version_, synapseDomain_)\n    {\n        agentManager = agentManager_;\n        inbox = inbox_;\n    }\n\n    // ════════════════════════════════════════════ ONLY AGENT MANAGER ═════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external onlyAgentManager {\n        uint40 openedAt = ChainContext.blockTimestamp();\n        DisputeStatus memory status = DisputeStatus({flag: DisputeFlag.Pending, openedAt: openedAt, resolvedAt: 0});\n        _disputes[guardIndex] = status;\n        _disputes[notaryIndex] = status;\n    }\n\n    /// @inheritdoc IAgentSecured\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external onlyAgentManager {\n        // Update the dispute status of the slashed agent first.\n        uint40 resolvedAt = ChainContext.blockTimestamp();\n        _disputes[slashedIndex].flag = DisputeFlag.Slashed;\n        _disputes[slashedIndex].resolvedAt = resolvedAt;\n        // Mark the rival agent as not disputed, if there was an ongoing dispute.\n        if (rivalIndex != 0) {\n            _disputes[rivalIndex].flag = DisputeFlag.None;\n            _disputes[rivalIndex].resolvedAt = resolvedAt;\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function agentStatus(address agent) external view returns (AgentStatus memory) {\n        return _agentStatus(agent);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status) {\n        return _getAgent(index);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory) {\n        return _disputes[agentIndex];\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns status of the given agent: (flag, domain, index).\n    function _agentStatus(address agent) internal view returns (AgentStatus memory) {\n        return IAgentManager(agentManager).agentStatus(agent);\n    }\n\n    /// @dev Returns agent and their status for a given agent index. Returns zero values for non existing indexes.\n    function _getAgent(uint256 index) internal view returns (address agent, AgentStatus memory status) {\n        return IAgentManager(agentManager).getAgent(index);\n    }\n\n    /// @dev Checks if a Dispute exists for the given Notary. This function returns true, if\n    /// Notary is in ongoing Dispute, or if Dispute was resolved not in Notary's favor.\n    /// In both cases we can't trust Notary's data.\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeExists(uint32 notaryIndex) internal view returns (bool) {\n        return _disputes[notaryIndex].flag != DisputeFlag.None;\n    }\n\n    /// @dev Checks if a Notary recently won a Dispute and is still in the \"post-dispute\" timeout period.\n    /// In this period we still can't trust Notary's data, though we can optimistically assume that\n    /// that the data will be correct after the timeout (assuming no new Disputes are opened).\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeTimeout(uint32 notaryIndex) internal view returns (bool) {\n        DisputeStatus memory status = _disputes[notaryIndex];\n        // Exit early if Notary is in ongoing Dispute / slashed.\n        if (status.flag != DisputeFlag.None) return false;\n        // Check if Notary has been in any Dispute at all.\n        if (status.openedAt == 0) return false;\n        // Otherwise check if the Dispute timeout is still active.\n        return block.timestamp \u003c status.resolvedAt + DISPUTE_TIMEOUT_NOTARY;\n    }\n}\n\n// contracts/hubs/StateHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StateHub` is a parent contract for `Origin`. It is responsible for the following:\n/// - Keeping track of the historical Origin Merkle Tree containing all the message hashes.\n/// - Keeping track of the historical Origin States, as well as verifying their validity.\nabstract contract StateHub is AgentSecured, StateHubEvents, IStateHub {\n    using SafeCast for uint256;\n    using StateLib for bytes;\n\n    struct OriginState {\n        uint40 blockNumber;\n        uint40 timestamp;\n        GasData gasData;\n    }\n    // Bits left for tight packing: 80\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Historical Merkle Tree\n    /// Note: Takes two storage slots\n    HistoricalTree private _tree;\n\n    /// @dev All historical contract States\n    OriginState[] private _originStates;\n\n    /// @dev gap for upgrade safety\n    uint256[47] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IStateHub\n    function isValidState(bytes memory statePayload) external view returns (bool isValid) {\n        // This will revert if payload is not a formatted state\n        State state = statePayload.castToState();\n        return _isValidState(state);\n    }\n\n    /// @inheritdoc IStateHub\n    function statesAmount() external view returns (uint256) {\n        return _originStates.length;\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestLatestState() external view returns (bytes memory stateData) {\n        // This never underflows, assuming the contract was initialized\n        return suggestState(_nextNonce() - 1);\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestState(uint32 nonce) public view returns (bytes memory stateData) {\n        // This will revert if nonce is out of range\n        bytes32 root = _tree.root(nonce);\n        return _formatOriginState(_originStates[nonce], root, localDomain, nonce);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Initializes the saved states list by inserting a state for an empty Merkle Tree.\n    function _initializeStates() internal {\n        // This should only be called once, when the contract is initialized\n        // This will revert if _tree.roots is non-empty\n        bytes32 savedRoot = _tree.initializeRoots();\n        // Save root for empty merkle _tree with block number and timestamp of initialization\n        _saveState(savedRoot, _toOriginState());\n    }\n\n    /// @dev Inserts leaf into the Merkle Tree and saves the updated origin State.\n    function _insertAndSave(bytes32 leaf) internal {\n        bytes32 newRoot = _tree.insert(leaf);\n        _saveState(newRoot, _toOriginState());\n    }\n\n    /// @dev Saves an updated state of the Origin contract\n    function _saveState(bytes32 root, OriginState memory state) internal {\n        uint32 nonce = _nextNonce();\n        _originStates.push(state);\n        // Emit event with raw state data\n        emit StateSaved(_formatOriginState(state, root, localDomain, nonce));\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns nonce of the next sent message: the amount of saved States so far.\n    /// This always equals to \"total amount of sent messages\" plus 1.\n    function _nextNonce() internal view returns (uint32) {\n        // TODO: consider using more than 32 bits for origin nonces\n        return _originStates.length.toUint32();\n    }\n\n    /// @dev Checks if a state is valid, i.e. if it matches the historical one.\n    /// Reverts, if state refers to another Origin contract.\n    function _isValidState(State state) internal view returns (bool) {\n        // Check if state refers to this contract\n        if (state.origin() != localDomain) revert IncorrectOriginDomain();\n        // Check if nonce exists\n        uint32 nonce = state.nonce();\n        if (nonce \u003e= _originStates.length) return false;\n        // Check if state root matches the historical one\n        if (state.root() != _tree.root(nonce)) return false;\n        // Check if state metadata matches the historical one\n        return _areEqual(state, _originStates[nonce]);\n    }\n\n    // ═════════════════════════════════════════════ STRUCT FORMATTING ═════════════════════════════════════════════════\n\n    /// @dev Returns a formatted payload for a stored OriginState.\n    function _formatOriginState(OriginState memory originState, bytes32 root, uint32 origin, uint32 nonce)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return StateLib.formatState({\n            root_: root,\n            origin_: origin,\n            nonce_: nonce,\n            blockNumber_: originState.blockNumber,\n            timestamp_: originState.timestamp,\n            gasData_: originState.gasData\n        });\n    }\n\n    /// @dev Child contract should implement the logic for getting the current gas data from the gas oracle\n    /// to be saved as part of the Origin State.\n    // solhint-disable-next-line ordering\n    function _fetchGasData() internal view virtual returns (GasData);\n\n    /// @dev Returns a OriginState struct to save in the contract.\n    function _toOriginState() internal view returns (OriginState memory originState) {\n        originState.blockNumber = ChainContext.blockNumber();\n        originState.timestamp = ChainContext.blockTimestamp();\n        originState.gasData = _fetchGasData();\n    }\n\n    /// @dev Checks that a state and its Origin representation are equal.\n    function _areEqual(State state, OriginState memory originState) internal pure returns (bool) {\n        return state.blockNumber() == originState.blockNumber \u0026\u0026 state.timestamp() == originState.timestamp;\n    }\n}\n\n// contracts/Origin.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Origin` contract is used for sending messages to remote chains. It is done\n/// by inserting the message hashes into the Origin Merkle, which makes it possible to\n/// prove that message was sent using the Merkle proof against the Origin Merkle Root. This essentially\n/// compresses the list of messages into a single 32-byte value that needs to be stored on the destination chain.\n/// `Origin` is responsible for the following:\n/// - Formatting the sent message payloads, and inserting their hashes into the Origin Merkle Tree.\n/// - Keeping track of its own historical states (see parent contract `StateHub`).\n/// - Enforcing minimum tip values for sent base messages based on the provided execution requests.\n/// - Distributing the collected tips upon request from a local `AgentManager` contract.\ncontract Origin is StateHub, OriginEvents, InterfaceOrigin {\n    using MemViewLib for bytes;\n    using MessageLib for bytes;\n    using TipsLib for bytes;\n    using TypeCasts for address;\n\n    address public immutable gasOracle;\n\n    modifier onlyRemoteDestination(uint32 destination) {\n        if (destination == localDomain) revert IncorrectDestinationDomain();\n        _;\n    }\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_, address gasOracle_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {\n        gasOracle = gasOracle_;\n    }\n\n    /// @notice Initializes Origin contract:\n    /// - msg.sender is set as contract owner\n    /// - State of \"empty merkle tree\" is saved\n    function initialize() external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize \"states\": state of an \"empty merkle tree\" is saved\n        _initializeStates();\n    }\n\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable onlyRemoteDestination(destination) returns (uint32 messageNonce, bytes32 messageHash) {\n        // Check that content is not too large\n        if (content.length \u003e MAX_CONTENT_BYTES) revert ContentLengthTooBig();\n        // This will revert if msg.value is lower than value of minimum tips\n        Tips tips = _getMinimumTips(destination, paddedRequest, content.length).matchValue(msg.value);\n        Request request = RequestLib.wrapPadded(paddedRequest);\n        // Format the BaseMessage body\n        bytes memory body = BaseMessageLib.formatBaseMessage({\n            sender_: msg.sender.addressToBytes32(),\n            recipient_: recipient,\n            tips_: tips,\n            request_: request,\n            content_: content\n        });\n        // Send the message\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Base, body);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        onlyAgentManager\n        onlyRemoteDestination(destination)\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // AgentManager (checked via modifier) is responsible for constructing the calldata payload correctly.\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Manager, payload);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function withdrawTips(address recipient, uint256 amount) external onlyAgentManager {\n        if (address(this).balance \u003c amount) revert InsufficientEthBalance();\n        (bool success,) = recipient.call{value: amount}(\"\");\n        if (!success) revert EthTransferFailed();\n        emit TipWithdrawalCompleted(recipient, amount);\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue)\n    {\n        return _getMinimumTips(destination, paddedRequest, contentLength).value();\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Sends the given message to the specified destination. Message hash is inserted\n    /// into the Origin Merkle Tree, which will enable message execution on destination chain.\n    function _sendMessage(uint32 destination, uint32 optimisticPeriod, MessageFlag flag, bytes memory body)\n        internal\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // Format the message header\n        messageNonce = _nextNonce();\n        Header header = flag.encodeHeader({\n            origin_: localDomain,\n            nonce_: messageNonce,\n            destination_: destination,\n            optimisticPeriod_: optimisticPeriod\n        });\n        // Format the full message payload\n        bytes memory msgPayload = MessageLib.formatMessage(header, body);\n        // Insert new leaf into the Origin Merkle Tree and save the updated state\n        messageHash = msgPayload.castToMessage().leaf();\n        _insertAndSave(messageHash);\n        // Emit event with message information\n        emit Sent(messageHash, messageNonce, destination, msgPayload);\n        // Update the gas oracle data. We do this after the provided tips are checked so that\n        // the provided message is sent in the event that the gas oracle data is updated to a higher value.\n        InterfaceGasOracle(gasOracle).updateGasData(destination);\n        // TODO: consider doing this before the message is sent, while adjusting GasOracle.getMinimumTips() to\n        // use the pending gas oracle data.\n    }\n\n    /// @dev Returns the minimum tips for sending a message to the given destination with the given request and content.\n    function _getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        internal\n        view\n        returns (Tips)\n    {\n        return\n            TipsLib.wrapPadded(InterfaceGasOracle(gasOracle).getMinimumTips(destination, paddedRequest, contentLength));\n    }\n\n    /// @dev Gets the current gas data from the gas oracle to be saved as part of the Origin State.\n    function _fetchGasData() internal view override returns (GasData) {\n        return GasDataLib.wrapGasData(InterfaceGasOracle(gasOracle).getGasData());\n    }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"","srcMapRuntime":"","abiDefinition":[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"Contract module which provides a basic access control mechanism, where there is an account (an owner) that can be granted exclusive access to specific functions. By default, the owner account will be the one that deploys the contract. This can later be changed with {transferOwnership}. This module is used through inheritance. It will make available the modifier `onlyOwner`, which can be applied to your functions to restrict their use to the owner.","kind":"dev","methods":{"owner()":{"details":"Returns the address of the current owner."},"renounceOwnership()":{"details":"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner."},"transferOwnership(address)":{"details":"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner."}},"stateVariables":{"__gap":{"details":"This empty reserved space is put in place to allow future versions to add new variables without shifting down storage in the inheritance chain. See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps"}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Contract module which provides a basic access control mechanism, where there is an account (an owner) that can be granted exclusive access to specific functions. By default, the owner account will be the one that deploys the contract. This can later be changed with {transferOwnership}. This module is used through inheritance. It will make available the modifier `onlyOwner`, which can be applied to your functions to restrict their use to the owner.\",\"kind\":\"dev\",\"methods\":{\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"}},\"stateVariables\":{\"__gap\":{\"details\":\"This empty reserved space is put in place to allow future versions to add new variables without shifting down storage in the inheritance chain. See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Origin.sol\":\"OwnableUpgradeable\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Origin.sol\":{\"keccak256\":\"0x96775924f147f3d1f8df8cdf56731fe52a15af8d8e12e608efb8158c112b18cd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e642a27f5fab3c62b4c02e9754e9e42b1cf2e5381dbea9d3d106d23b7772ebe6\",\"dweb:/ipfs/QmUwn7ZyBvPkjnMuK8ZMSexBUdNQnVtxwyoAyT4DXLQjra\"]}},\"version\":1}"},"hashes":{"owner()":"8da5cb5b","renounceOwnership()":"715018a6","transferOwnership(address)":"f2fde38b"}},"solidity/Origin.sol:RequestLib":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122012885b6c6c90285c7d4915395eec3d65d6e3c547999f14cb6e95df1ffbd5767764736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122012885b6c6c90285c7d4915395eec3d65d6e3c547999f14cb6e95df1ffbd5767764736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/OriginEvents.sol\n\n/// @notice A collection of events emitted by the Origin contract\nabstract contract OriginEvents {\n    /**\n     * @notice Emitted when a new message is sent.\n     * @param messageHash   Hash of message; the leaf inserted to the Merkle tree for the message\n     * @param nonce         Nonce of sent message (starts from 1)\n     * @param destination   Destination domain\n     * @param message       Raw bytes of message\n     */\n    event Sent(bytes32 indexed messageHash, uint32 indexed nonce, uint32 indexed destination, bytes message);\n\n    /**\n     * @notice Emitted when a tip withdrawal is completed.\n     * @param actor     Actor address\n     * @param tip       Tip value, denominated in local domain's wei\n     */\n    event TipWithdrawalCompleted(address actor, uint256 tip);\n}\n\n// contracts/events/StateHubEvents.sol\n\n/// @notice A collection of events emitted by the StateHub contract\nabstract contract StateHubEvents {\n    /**\n     * @notice Emitted when a new Origin State is saved after a message was sent.\n     * @param state     Raw payload with state data\n     */\n    event StateSaved(bytes state);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n    /**\n     * @notice Check that a given state is valid: matches the historical state of Origin contract.\n     * Note: any Agent including an invalid state in their snapshot will be slashed\n     * upon providing the snapshot and agent signature for it to Origin contract.\n     * @dev Will revert if any of these is true:\n     *  - State payload is not properly formatted.\n     * @param statePayload      Raw payload with state data\n     * @return isValid          Whether the provided state is valid\n     */\n    function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns the amount of saved states so far.\n     * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n     */\n    function statesAmount() external view returns (uint256);\n\n    /**\n     * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @return statePayload     Raw payload with the latest state data\n     */\n    function suggestLatestState() external view returns (bytes memory statePayload);\n\n    /**\n     * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @param nonce             Historical nonce to form a state\n     * @return statePayload     Raw payload with historical state data\n     */\n    function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/InterfaceGasOracle.sol\n\ninterface InterfaceGasOracle {\n    /**\n     * @notice Fetches the latest gas data for the chain from `Destination` contract,\n     * and uses it to update the oracle values for the requested chain.\n     * @param domain    Domain to update the gas data for\n     */\n    function updateGasData(uint32 domain) external;\n\n    /**\n     * @notice Returns the gas data for the local chain.\n     */\n    function getGasData() external view returns (uint256 paddedGasData);\n\n    /**\n     * @notice Returns the gas data for the given domain, in the decoded format.\n     * @param domain        Domain of chain to get gas data for\n     * @return gasPrice     Gas price for the chain (in Wei per gas unit)\n     * @return dataPrice    Calldata price (in Wei per byte of content)\n     * @return execBuffer   Tx fee safety buffer for message execution (in Wei)\n     * @return amortAttCost Amortized cost for attestation submission (in Wei)\n     * @return etherPrice   Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n     * @return markup       Markup for the message execution (in BWAD)\n     */\n    function getDecodedGasData(uint32 domain)\n        external\n        view\n        returns (\n            uint256 gasPrice,\n            uint256 dataPrice,\n            uint256 execBuffer,\n            uint256 amortAttCost,\n            uint256 etherPrice,\n            uint256 markup\n        );\n\n    /**\n     * @notice Returns the minimum tips for sending a message to a given destination.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return paddedTips       Padded encoded minimum tips information\n     */\n    function getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 paddedTips);\n}\n\n// contracts/interfaces/InterfaceOrigin.sol\n\ninterface InterfaceOrigin {\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /**\n     * @notice Send a message to the recipient located on destination domain.\n     * @dev Recipient has to conform to IMessageRecipient interface, otherwise message won't be delivered.\n     * Will revert if any of these is true:\n     * - `destination` is equal to contract's local domain\n     * - `content` length is greater than `MAX_CONTENT_BYTES`\n     * - `msg.value` is lower than value of minimum tips for the given message\n     * @param destination           Domain of destination chain\n     * @param recipient             Address of recipient on destination chain as bytes32\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param paddedRequest         Padded encoded message execution request on destination chain\n     * @param content               Raw bytes content of message\n     * @return messageNonce         Nonce of the sent message\n     * @return messageHash          Hash of the sent message\n     */\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable returns (uint32 messageNonce, bytes32 messageHash);\n\n    /**\n     * @notice Send a manager message to the destination domain.\n     * @dev This could only be called by AgentManager, which takes care of encoding the calldata payload.\n     * Note: (msgOrigin, proofMaturity) security args will be added to payload on the destination chain\n     * so that the AgentManager could verify where the Manager Message came from and how mature is the proof.\n     * Note: function is not payable, as no tips are required for sending a manager message.\n     * Will revert if `destination` is equal to contract's local domain.\n     * @param destination           Domain of destination chain\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param payload               Payload for calling AgentManager on destination chain (with extra security args)\n     */\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        returns (uint32 messageNonce, bytes32 messageHash);\n\n    // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Withdraws locked base message tips to the recipient.\n     * @dev Could only be called by a local AgentManager.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function withdrawTips(address recipient, uint256 amount) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the minimum tips value for sending a message to a given destination.\n     * @dev Using at least `tipsValue` as `msg.value` for `sendBaseMessage()`\n     * will guarantee that the message will be accepted.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return tipsValue        Minimum tips value for a message to be accepted\n     */\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue);\n}\n\n// contracts/libs/Constants.sol\n\n// Here we define common constants to enable their easier reusing later.\n\n// ══════════════════════════════════ MERKLE ═══════════════════════════════════\n/// @dev Height of the Agent Merkle Tree\nuint256 constant AGENT_TREE_HEIGHT = 32;\n/// @dev Height of the Origin Merkle Tree\nuint256 constant ORIGIN_TREE_HEIGHT = 32;\n/// @dev Height of the Snapshot Merkle Tree. Allows up to 64 leafs, e.g. up to 32 states\nuint256 constant SNAPSHOT_TREE_HEIGHT = 6;\n// ══════════════════════════════════ STRUCTS ══════════════════════════════════\n/// @dev See Attestation.sol: (bytes32,bytes32,uint32,uint40,uint40): 32+32+4+5+5\nuint256 constant ATTESTATION_LENGTH = 78;\n/// @dev See GasData.sol: (uint16,uint16,uint16,uint16,uint16,uint16): 2+2+2+2+2+2\nuint256 constant GAS_DATA_LENGTH = 12;\n/// @dev See Receipt.sol: (uint32,uint32,bytes32,bytes32,uint8,address,address,address): 4+4+32+32+1+20+20+20\nuint256 constant RECEIPT_LENGTH = 133;\n/// @dev See State.sol: (bytes32,uint32,uint32,uint40,uint40,GasData): 32+4+4+5+5+len(GasData)\nuint256 constant STATE_LENGTH = 50 + GAS_DATA_LENGTH;\n/// @dev Maximum amount of states in a single snapshot. Each state produces two leafs in the tree\nuint256 constant SNAPSHOT_MAX_STATES = 1 \u003c\u003c (SNAPSHOT_TREE_HEIGHT - 1);\n// ══════════════════════════════════ MESSAGE ══════════════════════════════════\n/// @dev See Header.sol: (uint8,uint32,uint32,uint32,uint32): 1+4+4+4+4\nuint256 constant HEADER_LENGTH = 17;\n/// @dev See Request.sol: (uint96,uint64,uint32): 12+8+4\nuint256 constant REQUEST_LENGTH = 24;\n/// @dev See Tips.sol: (uint64,uint64,uint64,uint64): 8+8+8+8\nuint256 constant TIPS_LENGTH = 32;\n/// @dev The amount of discarded last bits when encoding tip values\nuint256 constant TIPS_GRANULARITY = 32;\n/// @dev Tip values could be only the multiples of TIPS_MULTIPLIER\nuint256 constant TIPS_MULTIPLIER = 1 \u003c\u003c TIPS_GRANULARITY;\n// ══════════════════════════════ STATEMENT SALTS ══════════════════════════════\n/// @dev Salts for signing various statements\nbytes32 constant ATTESTATION_VALID_SALT = keccak256(\"ATTESTATION_VALID_SALT\");\nbytes32 constant ATTESTATION_INVALID_SALT = keccak256(\"ATTESTATION_INVALID_SALT\");\nbytes32 constant RECEIPT_VALID_SALT = keccak256(\"RECEIPT_VALID_SALT\");\nbytes32 constant RECEIPT_INVALID_SALT = keccak256(\"RECEIPT_INVALID_SALT\");\nbytes32 constant SNAPSHOT_VALID_SALT = keccak256(\"SNAPSHOT_VALID_SALT\");\nbytes32 constant STATE_INVALID_SALT = keccak256(\"STATE_INVALID_SALT\");\n// ═════════════════════════════════ PROTOCOL ══════════════════════════════════\n/// @dev Optimistic period for new agent roots in LightManager\nuint32 constant AGENT_ROOT_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Timeout between the agent root could be proposed and resolved in LightManager\nuint32 constant AGENT_ROOT_PROPOSAL_TIMEOUT = 12 hours;\nuint32 constant BONDING_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Amount of time that the Notary will not be considered active after they won a dispute\nuint32 constant DISPUTE_TIMEOUT_NOTARY = 12 hours;\n/// @dev Amount of time without fresh data from Notaries before contract owner can resolve stuck disputes manually\nuint256 constant FRESH_DATA_TIMEOUT = 4 hours;\n/// @dev Maximum bytes per message = 2 KiB (somewhat arbitrarily set to begin)\nuint256 constant MAX_CONTENT_BYTES = 2 * 2 ** 10;\n/// @dev Maximum value for the summit tip that could be set in GasOracle\nuint256 constant MAX_SUMMIT_TIP = 0.01 ether;\n\n// contracts/libs/Errors.sol\n\n// ══════════════════════════════ INVALID CALLER ═══════════════════════════════\n\nerror CallerNotAgentManager();\nerror CallerNotDestination();\nerror CallerNotInbox();\nerror CallerNotSummit();\n\n// ══════════════════════════════ INCORRECT DATA ═══════════════════════════════\n\nerror IncorrectAttestation();\nerror IncorrectAgentDomain();\nerror IncorrectAgentIndex();\nerror IncorrectAgentProof();\nerror IncorrectAgentRoot();\nerror IncorrectDataHash();\nerror IncorrectDestinationDomain();\nerror IncorrectOriginDomain();\nerror IncorrectSnapshotProof();\nerror IncorrectSnapshotRoot();\nerror IncorrectState();\nerror IncorrectStatesAmount();\nerror IncorrectTipsProof();\nerror IncorrectVersionLength();\n\nerror IncorrectNonce();\nerror IncorrectSender();\nerror IncorrectRecipient();\n\nerror FlagOutOfRange();\nerror IndexOutOfRange();\nerror NonceOutOfRange();\n\nerror OutdatedNonce();\n\nerror UnformattedAttestation();\nerror UnformattedAttestationReport();\nerror UnformattedBaseMessage();\nerror UnformattedCallData();\nerror UnformattedCallDataPrefix();\nerror UnformattedMessage();\nerror UnformattedReceipt();\nerror UnformattedReceiptReport();\nerror UnformattedSignature();\nerror UnformattedSnapshot();\nerror UnformattedState();\nerror UnformattedStateReport();\n\n// ═══════════════════════════════ MERKLE TREES ════════════════════════════════\n\nerror LeafNotProven();\nerror MerkleTreeFull();\nerror NotEnoughLeafs();\nerror TreeHeightTooLow();\n\n// ═════════════════════════════ OPTIMISTIC PERIOD ═════════════════════════════\n\nerror BaseClientOptimisticPeriod();\nerror MessageOptimisticPeriod();\nerror SlashAgentOptimisticPeriod();\nerror WithdrawTipsOptimisticPeriod();\nerror ZeroProofMaturity();\n\n// ═══════════════════════════════ AGENT MANAGER ═══════════════════════════════\n\nerror AgentNotGuard();\nerror AgentNotNotary();\n\nerror AgentCantBeAdded();\nerror AgentNotActive();\nerror AgentNotActiveNorUnstaking();\nerror AgentNotFraudulent();\nerror AgentNotUnstaking();\nerror AgentUnknown();\n\nerror AgentRootNotProposed();\nerror AgentRootTimeoutNotOver();\n\nerror NotStuck();\n\nerror DisputeAlreadyResolved();\nerror DisputeNotOpened();\nerror DisputeTimeoutNotOver();\nerror GuardInDispute();\nerror NotaryInDispute();\n\nerror MustBeSynapseDomain();\nerror SynapseDomainForbidden();\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\nerror AlreadyExecuted();\nerror AlreadyFailed();\nerror DuplicatedSnapshotRoot();\nerror IncorrectMagicValue();\nerror GasLimitTooLow();\nerror GasSuppliedTooLow();\n\n// ══════════════════════════════════ ORIGIN ═══════════════════════════════════\n\nerror ContentLengthTooBig();\nerror EthTransferFailed();\nerror InsufficientEthBalance();\n\n// ════════════════════════════════ GAS ORACLE ═════════════════════════════════\n\nerror LocalGasDataNotSet();\nerror RemoteGasDataNotSet();\n\n// ═══════════════════════════════════ TIPS ════════════════════════════════════\n\nerror SummitTipTooHigh();\nerror TipsClaimMoreThanEarned();\nerror TipsClaimZero();\nerror TipsOverflow();\nerror TipsValueTooLow();\n\n// ════════════════════════════════ MEMORY VIEW ════════════════════════════════\n\nerror IndexedTooMuch();\nerror ViewOverrun();\nerror OccupiedMemory();\nerror UnallocatedMemory();\nerror PrecompileOutOfGas();\n\n// ═════════════════════════════════ MULTICALL ═════════════════════════════════\n\nerror MulticallFailed();\n\n// contracts/libs/TypeCasts.sol\n\nlibrary TypeCasts {\n    // alignment preserving cast\n    function addressToBytes32(address addr) internal pure returns (bytes32) {\n        return bytes32(uint256(uint160(addr)));\n    }\n\n    // alignment preserving cast\n    function bytes32ToAddress(bytes32 buf) internal pure returns (address) {\n        return address(uint160(uint256(buf)));\n    }\n}\n\n// contracts/libs/stack/Number.sol\n\n/// Number is a compact representation of uint256, that is fit into 16 bits\n/// with the maximum relative error under 0.4%.\ntype Number is uint16;\n\nusing NumberLib for Number global;\n\n/// # Number\n/// Library for compact representation of uint256 numbers.\n/// - Number is stored using mantissa and exponent, each occupying 8 bits.\n/// - Numbers under 2**8 are stored as `mantissa` with `exponent = 0xFF`.\n/// - Numbers at least 2**8 are approximated as `(256 + mantissa) \u003c\u003c exponent`\n/// \u003e - `0 \u003c= mantissa \u003c 256`\n/// \u003e - `0 \u003c= exponent \u003c= 247` (`256 * 2**248` doesn't fit into uint256)\n/// # Number stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type  | Bytes |\n/// | ---------- | -------- | ----- | ----- |\n/// | (002..001] | mantissa | uint8 | 1     |\n/// | (001..000] | exponent | uint8 | 1     |\n\nlibrary NumberLib {\n    /// @dev Amount of bits to shift to mantissa field\n    uint16 private constant SHIFT_MANTISSA = 8;\n\n    /// @notice For bwad math (binary wad) we use 2**64 as \"wad\" unit.\n    /// @dev We are using not using 10**18 as wad, because it is not stored precisely in NumberLib.\n    uint256 internal constant BWAD_SHIFT = 64;\n    uint256 internal constant BWAD = 1 \u003c\u003c BWAD_SHIFT;\n    /// @notice ~0.1% in bwad units.\n    uint256 internal constant PER_MILLE_SHIFT = BWAD_SHIFT - 10;\n    uint256 internal constant PER_MILLE = 1 \u003c\u003c PER_MILLE_SHIFT;\n\n    /// @notice Compresses uint256 number into 16 bits.\n    function compress(uint256 value) internal pure returns (Number) {\n        // Find `msb` such as `2**msb \u003c= value \u003c 2**(msb + 1)`\n        uint256 msb = mostSignificantBit(value);\n        // We want to preserve 9 bits of precision.\n        // The highest bit is always 1, so we can skip it.\n        // The remaining 8 highest bits are stored as mantissa.\n        if (msb \u003c 8) {\n            // Value is less than 2**8, so we can use value as mantissa with \"-1\" exponent.\n            return _encode(uint8(value), 0xFF);\n        } else {\n            // We use `msb - 8` as exponent otherwise. Note that `exponent \u003e= 0`.\n            unchecked {\n                uint256 exponent = msb - 8;\n                // Shifting right by `msb-8` bits will shift the \"remaining 8 highest bits\" into the 8 lowest bits.\n                // uint8() will truncate the highest bit.\n                return _encode(uint8(value \u003e\u003e exponent), uint8(exponent));\n            }\n        }\n    }\n\n    /// @notice Decompresses 16 bits number into uint256.\n    /// @dev The outcome is an approximation of the original number: `(value - value / 256) \u003c number \u003c= value`.\n    function decompress(Number number) internal pure returns (uint256 value) {\n        // Isolate 8 highest bits as the mantissa.\n        uint256 mantissa = Number.unwrap(number) \u003e\u003e SHIFT_MANTISSA;\n        // This will truncate the highest bits, leaving only the exponent.\n        uint256 exponent = uint8(Number.unwrap(number));\n        if (exponent == 0xFF) {\n            return mantissa;\n        } else {\n            unchecked {\n                return (256 + mantissa) \u003c\u003c (exponent);\n            }\n        }\n    }\n\n    /// @dev Returns the most significant bit of `x`\n    /// https://solidity-by-example.org/bitwise/\n    function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\n        // To find `msb` we determine it bit by bit, starting from the highest one.\n        // `0 \u003c= msb \u003c= 255`, so we start from the highest bit, 1\u003c\u003c7 == 128.\n        // If `x` is at least 2**128, then the highest bit of `x` is at least 128.\n        // solhint-disable no-inline-assembly\n        assembly {\n            // `f` is set to 1\u003c\u003c7 if `x \u003e= 2**128` and to 0 otherwise.\n            let f := shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\n            // If `x \u003e= 2**128` then set `msb` highest bit to 1 and shift `x` right by 128.\n            // Otherwise, `msb` remains 0 and `x` remains unchanged.\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        // `x` is now at most 2**128 - 1. Continue the same way, the next highest bit is 1\u003c\u003c6 == 64.\n        assembly {\n            // `f` is set to 1\u003c\u003c6 if `x \u003e= 2**64` and to 0 otherwise.\n            let f := shl(6, gt(x, 0xFFFFFFFFFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c5 if `x \u003e= 2**32` and to 0 otherwise.\n            let f := shl(5, gt(x, 0xFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c4 if `x \u003e= 2**16` and to 0 otherwise.\n            let f := shl(4, gt(x, 0xFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c3 if `x \u003e= 2**8` and to 0 otherwise.\n            let f := shl(3, gt(x, 0xFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c2 if `x \u003e= 2**4` and to 0 otherwise.\n            let f := shl(2, gt(x, 0xF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c1 if `x \u003e= 2**2` and to 0 otherwise.\n            let f := shl(1, gt(x, 0x3))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1 if `x \u003e= 2**1` and to 0 otherwise.\n            let f := gt(x, 0x1)\n            msb := or(msb, f)\n        }\n    }\n\n    /// @dev Wraps (mantissa, exponent) pair into Number.\n    function _encode(uint8 mantissa, uint8 exponent) private pure returns (Number) {\n        // Casts below are upcasts, so they are safe.\n        return Number.wrap(uint16(mantissa) \u003c\u003c SHIFT_MANTISSA | uint16(exponent));\n    }\n}\n\n// contracts/libs/stack/Request.sol\n\n/// Request is encoded data with \"message execution request\".\ntype Request is uint192;\n\nusing RequestLib for Request global;\n\n/// Library for formatting _the request part_ of _the base messages_.\n/// - Request represents a message sender requirements for the message execution on the destination chain.\n/// - Request occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n/// \u003e gasDrop field is included for future compatibility and is ignored at the moment.\n///\n/// # Request stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type   | Bytes | Description                                          |\n/// | ---------- | -------- | ------ | ----- | ---------------------------------------------------- |\n/// | (024..012] | gasDrop  | uint96 | 12    | Minimum amount of gas token to drop to the recipient |\n/// | (012..004] | gasLimit | uint64 | 8     | Minimum amount of gas units to supply for execution  |\n/// | (004..000] | version  | uint32 | 4     | Base message version to pass to the recipient        |\n\nlibrary RequestLib {\n    /// @dev Amount of bits to shift to gasDrop field\n    uint192 private constant SHIFT_GAS_DROP = 12 * 8;\n    /// @dev Amount of bits to shift to gasLimit field\n    uint192 private constant SHIFT_GAS_LIMIT = 4 * 8;\n\n    /// @notice Returns an encoded request with the given fields\n    /// @param gasDrop_     Minimum amount of gas token to drop to the recipient (ignored at the moment)\n    /// @param gasLimit_    Minimum amount of gas units to supply for execution\n    /// @param version_     Base message version to pass to the recipient\n    function encodeRequest(uint96 gasDrop_, uint64 gasLimit_, uint32 version_) internal pure returns (Request) {\n        // Casts below are upcasts, so they are safe\n        return Request.wrap(uint192(gasDrop_) \u003c\u003c SHIFT_GAS_DROP | uint192(gasLimit_) \u003c\u003c SHIFT_GAS_LIMIT | version_);\n    }\n\n    /// @notice Wraps the padded encoded request into a Request-typed value.\n    /// @dev The \"padded\" request is simply an encoded request casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded requests\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedRequest) internal pure returns (Request) {\n        // Casting to uint192 will truncate the highest bits, which is the behavior we want\n        return Request.wrap(uint192(paddedRequest));\n    }\n\n    /// @notice Returns the requested of gas token to drop to the recipient.\n    function gasDrop(Request request) internal pure returns (uint96) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return uint96(Request.unwrap(request) \u003e\u003e SHIFT_GAS_DROP);\n    }\n\n    /// @notice Returns the requested minimum amount of gas units to supply for execution.\n    function gasLimit(Request request) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Request.unwrap(request) \u003e\u003e SHIFT_GAS_LIMIT);\n    }\n\n    /// @notice Returns the requested base message version to pass to the recipient.\n    function version(Request request) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Request.unwrap(request));\n    }\n}\n\n// node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        require(value \u003c= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        require(value \u003c= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        require(value \u003c= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value \u003c= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        require(value \u003c= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        require(value \u003c= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        require(value \u003c= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        require(value \u003c= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        require(value \u003c= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        require(value \u003c= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        require(value \u003c= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        require(value \u003c= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        require(value \u003c= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        require(value \u003c= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        require(value \u003c= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value \u003c= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        require(value \u003c= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        require(value \u003c= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        require(value \u003c= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value \u003c= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        require(value \u003c= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        require(value \u003c= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        require(value \u003c= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value \u003c= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        require(value \u003c= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        require(value \u003c= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        require(value \u003c= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value \u003c= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        require(value \u003c= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value \u003c= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value \u003c= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     *\n     * _Available since v3.0._\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value \u003e= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     *\n     * _Available since v3.0._\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value \u003c= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     *\n     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length \u003e 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance \u003e= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance \u003e= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length \u003e 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n\n// contracts/base/MultiCallable.sol\n\n/// @notice Collection of Multicall utilities. Fork of Multicall3:\n/// https://github.com/mds1/multicall/blob/master/src/Multicall3.sol\nabstract contract MultiCallable {\n    struct Call {\n        bool allowFailure;\n        bytes callData;\n    }\n\n    struct Result {\n        bool success;\n        bytes returnData;\n    }\n\n    /// @notice Aggregates a few calls to this contract into one multicall without modifying `msg.sender`.\n    function multicall(Call[] calldata calls) external returns (Result[] memory callResults) {\n        uint256 amount = calls.length;\n        callResults = new Result[](amount);\n        Call calldata call_;\n        for (uint256 i = 0; i \u003c amount;) {\n            call_ = calls[i];\n            Result memory result = callResults[i];\n            // We perform a delegate call to ourselves here. Delegate call does not modify `msg.sender`, so\n            // this will have the same effect as if `msg.sender` performed all the calls themselves one by one.\n            // solhint-disable-next-line avoid-low-level-calls\n            (result.success, result.returnData) = address(this).delegatecall(call_.callData);\n            // solhint-disable-next-line no-inline-assembly\n            assembly {\n                // Revert if the call fails and failure is not allowed\n                // `allowFailure := calldataload(call_)` and `success := mload(result)`\n                if iszero(or(calldataload(call_), mload(result))) {\n                    // Revert with `0x4d6a2328` (function selector for `MulticallFailed()`)\n                    mstore(0x00, 0x4d6a232800000000000000000000000000000000000000000000000000000000)\n                    revert(0x00, 0x04)\n                }\n            }\n            unchecked {\n                ++i;\n            }\n        }\n    }\n}\n\n// contracts/base/Version.sol\n\n/**\n * @title Versioned\n * @notice Version getter for contracts. Doesn't use any storage slots, meaning\n * it will never cause any troubles with the upgradeable contracts. For instance, this contract\n * can be added or removed from the inheritance chain without shifting the storage layout.\n */\nabstract contract Versioned {\n    /**\n     * @notice Struct that is mimicking the storage layout of a string with 32 bytes or less.\n     * Length is limited by 32, so the whole string payload takes two memory words:\n     * @param length    String length\n     * @param data      String characters\n     */\n    struct _ShortString {\n        uint256 length;\n        bytes32 data;\n    }\n\n    /// @dev Length of the \"version string\"\n    uint256 private immutable _length;\n    /// @dev Bytes representation of the \"version string\".\n    /// Strings with length over 32 are not supported!\n    bytes32 private immutable _data;\n\n    constructor(string memory version_) {\n        _length = bytes(version_).length;\n        if (_length \u003e 32) revert IncorrectVersionLength();\n        // bytes32 is left-aligned =\u003e this will store the byte representation of the string\n        // with the trailing zeroes to complete the 32-byte word\n        _data = bytes32(bytes(version_));\n    }\n\n    function version() external view returns (string memory versionString) {\n        // Load the immutable values to form the version string\n        _ShortString memory str = _ShortString(_length, _data);\n        // The only way to do this cast is doing some dirty assembly\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            versionString := str\n        }\n    }\n}\n\n// contracts/libs/ChainContext.sol\n\n/// @notice Library for accessing chain context variables as tightly packed integers.\n/// Messaging contracts should rely on this library for accessing chain context variables\n/// instead of doing the casting themselves.\nlibrary ChainContext {\n    using SafeCast for uint256;\n\n    /// @notice Returns the current block number as uint40.\n    /// @dev Reverts if block number is greater than 40 bits, which is not supposed to happen\n    /// until the block.timestamp overflows (assuming block time is at least 1 second).\n    function blockNumber() internal view returns (uint40) {\n        return block.number.toUint40();\n    }\n\n    /// @notice Returns the current block timestamp as uint40.\n    /// @dev Reverts if block timestamp is greater than 40 bits, which is\n    /// supposed to happen approximately in year 36835.\n    function blockTimestamp() internal view returns (uint40) {\n        return block.timestamp.toUint40();\n    }\n\n    /// @notice Returns the chain id as uint32.\n    /// @dev Reverts if chain id is greater than 32 bits, which is not\n    /// supposed to happen in production.\n    function chainId() internal view returns (uint32) {\n        return block.chainid.toUint32();\n    }\n}\n\n// contracts/libs/Structures.sol\n\n// Here we define common enums and structures to enable their easier reusing later.\n\n// ═══════════════════════════════ AGENT STATUS ════════════════════════════════\n\n/// @dev Potential statuses for the off-chain bonded agent:\n/// - Unknown: never provided a bond =\u003e signature not valid\n/// - Active: has a bond in BondingManager =\u003e signature valid\n/// - Unstaking: has a bond in BondingManager, initiated the unstaking =\u003e signature not valid\n/// - Resting: used to have a bond in BondingManager, successfully unstaked =\u003e signature not valid\n/// - Fraudulent: proven to commit fraud, value in Merkle Tree not updated =\u003e signature not valid\n/// - Slashed: proven to commit fraud, value in Merkle Tree was updated =\u003e signature not valid\n/// Unstaked agent could later be added back to THE SAME domain by staking a bond again.\n/// Honest agent: Unknown -\u003e Active -\u003e unstaking -\u003e Resting -\u003e Active ...\n/// Malicious agent: Unknown -\u003e Active -\u003e Fraudulent -\u003e Slashed\n/// Malicious agent: Unknown -\u003e Active -\u003e Unstaking -\u003e Fraudulent -\u003e Slashed\nenum AgentFlag {\n    Unknown,\n    Active,\n    Unstaking,\n    Resting,\n    Fraudulent,\n    Slashed\n}\n\n/// @notice Struct for storing an agent in the BondingManager contract.\nstruct AgentStatus {\n    AgentFlag flag;\n    uint32 domain;\n    uint32 index;\n}\n// 184 bits available for tight packing\n\nusing StructureUtils for AgentStatus global;\n\n/// @notice Potential statuses of an agent in terms of being in dispute\n/// - None: agent is not in dispute\n/// - Pending: agent is in unresolved dispute\n/// - Slashed: agent was in dispute that lead to agent being slashed\n/// Note: agent who won the dispute has their status reset to None\nenum DisputeFlag {\n    None,\n    Pending,\n    Slashed\n}\n\n/// @notice Struct for storing dispute status of an agent.\n/// @param flag         Dispute flag: None/Pending/Slashed.\n/// @param openedAt     Timestamp when the latest agent dispute was opened (zero if not opened).\n/// @param resolvedAt   Timestamp when the latest agent dispute was resolved (zero if not resolved).\nstruct DisputeStatus {\n    DisputeFlag flag;\n    uint40 openedAt;\n    uint40 resolvedAt;\n}\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\n/// @notice Struct representing the status of Destination contract.\n/// @param snapRootTime     Timestamp when latest snapshot root was accepted\n/// @param agentRootTime    Timestamp when latest agent root was accepted\n/// @param notaryIndex      Index of Notary who signed the latest agent root\nstruct DestinationStatus {\n    uint40 snapRootTime;\n    uint40 agentRootTime;\n    uint32 notaryIndex;\n}\n\n// ═══════════════════════════════ EXECUTION HUB ═══════════════════════════════\n\n/// @notice Potential statuses of the message in Execution Hub.\n/// - None: there hasn't been a valid attempt to execute the message yet\n/// - Failed: there was a valid attempt to execute the message, but recipient reverted\n/// - Success: there was a valid attempt to execute the message, and recipient did not revert\n/// Note: message can be executed until its status is Success\nenum MessageStatus {\n    None,\n    Failed,\n    Success\n}\n\nlibrary StructureUtils {\n    /// @notice Checks that Agent is Active\n    function verifyActive(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active) {\n            revert AgentNotActive();\n        }\n    }\n\n    /// @notice Checks that Agent is Unstaking\n    function verifyUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Unstaking) {\n            revert AgentNotUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Active or Unstaking\n    function verifyActiveUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active \u0026\u0026 status.flag != AgentFlag.Unstaking) {\n            revert AgentNotActiveNorUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Fraudulent\n    function verifyFraudulent(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Fraudulent) {\n            revert AgentNotFraudulent();\n        }\n    }\n\n    /// @notice Checks that Agent is not Unknown\n    function verifyKnown(AgentStatus memory status) internal pure {\n        if (status.flag == AgentFlag.Unknown) {\n            revert AgentUnknown();\n        }\n    }\n}\n\n// contracts/libs/memory/MemView.sol\n\n/// @dev MemView is an untyped view over a portion of memory to be used instead of `bytes memory`\ntype MemView is uint256;\n\n/// @dev Attach library functions to MemView\nusing MemViewLib for MemView global;\n\n/// @notice Library for operations with the memory views.\n/// Forked from https://github.com/summa-tx/memview-sol with several breaking changes:\n/// - The codebase is ported to Solidity 0.8\n/// - Custom errors are added\n/// - The runtime type checking is replaced with compile-time check provided by User-Defined Value Types\n///   https://docs.soliditylang.org/en/latest/types.html#user-defined-value-types\n/// - uint256 is used as the underlying type for the \"memory view\" instead of bytes29.\n///   It is wrapped into MemView custom type in order not to be confused with actual integers.\n/// - Therefore the \"type\" field is discarded, allowing to allocate 16 bytes for both view location and length\n/// - The documentation is expanded\n/// - Library functions unused by the rest of the codebase are removed\n//  - Very pretty code separators are added :)\nlibrary MemViewLib {\n    /// @notice Stack layout for uint256 (from highest bits to lowest)\n    /// (32 .. 16]      loc     16 bytes    Memory address of underlying bytes\n    /// (16 .. 00]      len     16 bytes    Length of underlying bytes\n\n    // ═══════════════════════════════════════════ BUILDING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Instantiate a new untyped memory view. This should generally not be called directly.\n     * Prefer `ref` wherever possible.\n     * @param loc_          The memory address\n     * @param len_          The length\n     * @return The new view with the specified location and length\n     */\n    function build(uint256 loc_, uint256 len_) internal pure returns (MemView) {\n        uint256 end_ = loc_ + len_;\n        // Make sure that a view is not constructed that points to unallocated memory\n        // as this could be indicative of a buffer overflow attack\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            if gt(end_, mload(0x40)) { end_ := 0 }\n        }\n        if (end_ == 0) {\n            revert UnallocatedMemory();\n        }\n        return _unsafeBuildUnchecked(loc_, len_);\n    }\n\n    /**\n     * @notice Instantiate a memory view from a byte array.\n     * @dev Note that due to Solidity memory representation, it is not possible to\n     * implement a deref, as the `bytes` type stores its len in memory.\n     * @param arr           The byte array\n     * @return The memory view over the provided byte array\n     */\n    function ref(bytes memory arr) internal pure returns (MemView) {\n        uint256 len_ = arr.length;\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 loc_;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // We add 0x20, so that the view starts exactly where the array data starts\n            loc_ := add(arr, 0x20)\n        }\n        return build(loc_, len_);\n    }\n\n    // ════════════════════════════════════════════ CLONING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to the new memory.\n     * @param memView       The memory view\n     * @return arr          The cloned byte array\n     */\n    function clone(MemView memView) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        unchecked {\n            _unsafeCopyTo(memView, ptr + 0x20);\n        }\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 len_ = memView.len();\n        uint256 footprint_ = memView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    /**\n     * @notice Copies all views, joins them into a new bytearray.\n     * @param memViews      The memory views\n     * @return arr          The new byte array with joined data behind the given views\n     */\n    function join(MemView[] memory memViews) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        MemView newView;\n        unchecked {\n            newView = _unsafeJoin(memViews, ptr + 0x20);\n        }\n        uint256 len_ = newView.len();\n        uint256 footprint_ = newView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    // ══════════════════════════════════════════ INSPECTING MEMORY VIEW ═══════════════════════════════════════════════\n\n    /**\n     * @notice Returns the memory address of the underlying bytes.\n     * @param memView       The memory view\n     * @return loc_         The memory address\n     */\n    function loc(MemView memView) internal pure returns (uint256 loc_) {\n        // loc is stored in the highest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u003e\u003e 128;\n    }\n\n    /**\n     * @notice Returns the number of bytes of the view.\n     * @param memView       The memory view\n     * @return len_         The length of the view\n     */\n    function len(MemView memView) internal pure returns (uint256 len_) {\n        // len is stored in the lowest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u0026 type(uint128).max;\n    }\n\n    /**\n     * @notice Returns the endpoint of `memView`.\n     * @param memView       The memory view\n     * @return end_         The endpoint of `memView`\n     */\n    function end(MemView memView) internal pure returns (uint256 end_) {\n        // The endpoint never overflows uint128, let alone uint256, so we could use unchecked math here\n        unchecked {\n            return memView.loc() + memView.len();\n        }\n    }\n\n    /**\n     * @notice Returns the number of memory words this memory view occupies, rounded up.\n     * @param memView       The memory view\n     * @return words_       The number of memory words\n     */\n    function words(MemView memView) internal pure returns (uint256 words_) {\n        // returning ceil(length / 32.0)\n        unchecked {\n            return (memView.len() + 31) \u003e\u003e 5;\n        }\n    }\n\n    /**\n     * @notice Returns the in-memory footprint of a fresh copy of the view.\n     * @param memView       The memory view\n     * @return footprint_   The in-memory footprint of a fresh copy of the view.\n     */\n    function footprint(MemView memView) internal pure returns (uint256 footprint_) {\n        // words() * 32\n        return memView.words() \u003c\u003c 5;\n    }\n\n    // ════════════════════════════════════════════ HASHING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the keccak256 hash of the underlying memory\n     * @param memView       The memory view\n     * @return digest       The keccak256 hash of the underlying memory\n     */\n    function keccak(MemView memView) internal pure returns (bytes32 digest) {\n        uint256 loc_ = memView.loc();\n        uint256 len_ = memView.len();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            digest := keccak256(loc_, len_)\n        }\n    }\n\n    /**\n     * @notice Adds a salt to the keccak256 hash of the underlying data and returns the keccak256 hash of the\n     * resulting data.\n     * @param memView       The memory view\n     * @return digestSalted keccak256(salt, keccak256(memView))\n     */\n    function keccakSalted(MemView memView, bytes32 salt) internal pure returns (bytes32 digestSalted) {\n        return keccak256(bytes.concat(salt, memView.keccak()));\n    }\n\n    // ════════════════════════════════════════════ SLICING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Safe slicing without memory modification.\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the given index\n     */\n    function slice(MemView memView, uint256 index_, uint256 len_) internal pure returns (MemView) {\n        uint256 loc_ = memView.loc();\n        // Ensure it doesn't overrun the view\n        if (loc_ + index_ + len_ \u003e memView.end()) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // loc_ + index_ \u003c= memView.end()\n            return build({loc_: loc_ + index_, len_: len_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing bytes from `index` to end(memView).\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @return The new view for the slice starting from the given index until the initial view endpoint\n     */\n    function sliceFrom(MemView memView, uint256 index_) internal pure returns (MemView) {\n        uint256 len_ = memView.len();\n        // Ensure it doesn't overrun the view\n        if (index_ \u003e len_) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // index_ \u003c= len_ =\u003e memView.loc() + index_ \u003c= memView.loc() + memView.len() == memView.end()\n            return build({loc_: memView.loc() + index_, len_: len_ - index_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the first `len` bytes.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the initial view beginning\n     */\n    function prefix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        return memView.slice({index_: 0, len_: len_});\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the last `len` byte.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length until the initial view endpoint\n     */\n    function postfix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        uint256 viewLen = memView.len();\n        // Ensure it doesn't overrun the view\n        if (len_ \u003e viewLen) {\n            revert ViewOverrun();\n        }\n        // Could do the unchecked math due to the check above\n        uint256 index_;\n        unchecked {\n            index_ = viewLen - len_;\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // len_ \u003c= memView.len() =\u003e memView.loc() \u003c= loc_ \u003c= memView.end()\n            return build({loc_: memView.loc() + viewLen - len_, len_: len_});\n        }\n    }\n\n    // ═══════════════════════════════════════════ INDEXING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Load up to 32 bytes from the view onto the stack.\n     * @dev Returns a bytes32 with only the `bytes_` HIGHEST bytes set.\n     * This can be immediately cast to a smaller fixed-length byte array.\n     * To automatically cast to an integer, use `indexUint`.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return result       The 32 byte result having only `bytes_` highest bytes set\n     */\n    function index(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (bytes32 result) {\n        if (bytes_ == 0) {\n            return bytes32(0);\n        }\n        // Can't load more than 32 bytes to the stack in one go\n        if (bytes_ \u003e 32) {\n            revert IndexedTooMuch();\n        }\n        // The last indexed byte should be within view boundaries\n        if (index_ + bytes_ \u003e memView.len()) {\n            revert ViewOverrun();\n        }\n        uint256 bitLength = bytes_ \u003c\u003c 3; // bytes_ * 8\n        uint256 loc_ = memView.loc();\n        // Get a mask with `bitLength` highest bits set\n        uint256 mask;\n        // 0x800...00 binary representation is 100...00\n        // sar stands for \"signed arithmetic shift\": https://en.wikipedia.org/wiki/Arithmetic_shift\n        // sar(N-1, 100...00) = 11...100..00, with exactly N highest bits set to 1\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            mask := sar(sub(bitLength, 1), 0x8000000000000000000000000000000000000000000000000000000000000000)\n        }\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load a full word using index offset, and apply mask to ignore non-relevant bytes\n            result := and(mload(add(loc_, index_)), mask)\n        }\n    }\n\n    /**\n     * @notice Parse an unsigned integer from the view at `index`.\n     * @dev Requires that the view have \u003e= `bytes_` bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return The unsigned integer\n     */\n    function indexUint(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (uint256) {\n        bytes32 indexedBytes = memView.index(index_, bytes_);\n        // `index()` returns left-aligned `bytes_`, while integers are right-aligned\n        // Shifting here to right-align with the full 32 bytes word: need to shift right `(32 - bytes_)` bytes\n        unchecked {\n            // memView.index() reverts when bytes_ \u003e 32, thus unchecked math\n            return uint256(indexedBytes) \u003e\u003e ((32 - bytes_) \u003c\u003c 3);\n        }\n    }\n\n    /**\n     * @notice Parse an address from the view at `index`.\n     * @dev Requires that the view have \u003e= 20 bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @return The address\n     */\n    function indexAddress(MemView memView, uint256 index_) internal pure returns (address) {\n        // index 20 bytes as `uint160`, and then cast to `address`\n        return address(uint160(memView.indexUint(index_, 20)));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns a memory view over the specified memory location\n    /// without checking if it points to unallocated memory.\n    function _unsafeBuildUnchecked(uint256 loc_, uint256 len_) private pure returns (MemView) {\n        // There is no scenario where loc or len would overflow uint128, so we omit this check.\n        // We use the highest 128 bits to encode the location and the lowest 128 bits to encode the length.\n        return MemView.wrap((loc_ \u003c\u003c 128) | len_);\n    }\n\n    /**\n     * @notice Copy the view to a location, return an unsafe memory reference\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memView       The memory view\n     * @param newLoc        The new location to copy the underlying view data\n     * @return The memory view over the unsafe memory with the copied underlying data\n     */\n    function _unsafeCopyTo(MemView memView, uint256 newLoc) private view returns (MemView) {\n        uint256 len_ = memView.len();\n        uint256 oldLoc = memView.loc();\n\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (newLoc \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        bool res;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // use the identity precompile (0x04) to copy\n            res := staticcall(gas(), 0x04, oldLoc, len_, newLoc, len_)\n        }\n        if (!res) revert PrecompileOutOfGas();\n        return _unsafeBuildUnchecked({loc_: newLoc, len_: len_});\n    }\n\n    /**\n     * @notice Join the views in memory, return an unsafe reference to the memory.\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memViews      The memory views\n     * @return The conjoined view pointing to the new memory\n     */\n    function _unsafeJoin(MemView[] memory memViews, uint256 location) private view returns (MemView) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (location \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        // Copy the views to the specified location one by one, by tracking the amount of copied bytes so far\n        uint256 offset = 0;\n        for (uint256 i = 0; i \u003c memViews.length;) {\n            MemView memView = memViews[i];\n            // We can use the unchecked math here as location + sum(view.length) will never overflow uint256\n            unchecked {\n                _unsafeCopyTo(memView, location + offset);\n                offset += memView.len();\n                ++i;\n            }\n        }\n        return _unsafeBuildUnchecked({loc_: location, len_: offset});\n    }\n}\n\n// contracts/libs/merkle/MerkleMath.sol\n\nlibrary MerkleMath {\n    // ═════════════════════════════════════════ BASIC MERKLE CALCULATIONS ═════════════════════════════════════════════\n\n    /**\n     * @notice Calculates the merkle root for the given leaf and merkle proof.\n     * @dev Will revert if proof length exceeds the tree height.\n     * @param index     Index of `leaf` in tree\n     * @param leaf      Leaf of the merkle tree\n     * @param proof     Proof of inclusion of `leaf` in the tree\n     * @param height    Height of the merkle tree\n     * @return root_    Calculated Merkle Root\n     */\n    function proofRoot(uint256 index, bytes32 leaf, bytes32[] memory proof, uint256 height)\n        internal\n        pure\n        returns (bytes32 root_)\n    {\n        // Proof length could not exceed the tree height\n        uint256 proofLen = proof.length;\n        if (proofLen \u003e height) revert TreeHeightTooLow();\n        root_ = leaf;\n        /// @dev Apply unchecked to all ++h operations\n        unchecked {\n            // Go up the tree levels from the leaf following the proof\n            for (uint256 h = 0; h \u003c proofLen; ++h) {\n                // Get a sibling node on current level: this is proof[h]\n                root_ = getParent(root_, proof[h], index, h);\n            }\n            // Go up to the root: the remaining siblings are EMPTY\n            for (uint256 h = proofLen; h \u003c height; ++h) {\n                root_ = getParent(root_, bytes32(0), index, h);\n            }\n        }\n    }\n\n    /**\n     * @notice Calculates the parent of a node on the path from one of the leafs to root.\n     * @param node          Node on a path from tree leaf to root\n     * @param sibling       Sibling for a given node\n     * @param leafIndex     Index of the tree leaf\n     * @param nodeHeight    \"Level height\" for `node` (ZERO for leafs, ORIGIN_TREE_HEIGHT for root)\n     */\n    function getParent(bytes32 node, bytes32 sibling, uint256 leafIndex, uint256 nodeHeight)\n        internal\n        pure\n        returns (bytes32 parent)\n    {\n        // Index for `node` on its \"tree level\" is (leafIndex / 2**height)\n        // \"Left child\" has even index, \"right child\" has odd index\n        if ((leafIndex \u003e\u003e nodeHeight) \u0026 1 == 0) {\n            // Left child\n            return getParent(node, sibling);\n        } else {\n            // Right child\n            return getParent(sibling, node);\n        }\n    }\n\n    /// @notice Calculates the parent of tow nodes in the merkle tree.\n    /// @dev We use implementation with H(0,0) = 0\n    /// This makes EVERY empty node in the tree equal to ZERO,\n    /// saving us from storing H(0,0), H(H(0,0), H(0, 0)), and so on\n    /// @param leftChild    Left child of the calculated node\n    /// @param rightChild   Right child of the calculated node\n    /// @return parent      Value for the node having above mentioned children\n    function getParent(bytes32 leftChild, bytes32 rightChild) internal pure returns (bytes32 parent) {\n        if (leftChild == bytes32(0) \u0026\u0026 rightChild == bytes32(0)) {\n            return 0;\n        } else {\n            return keccak256(bytes.concat(leftChild, rightChild));\n        }\n    }\n\n    // ════════════════════════════════ ROOT/PROOF CALCULATION FOR A LIST OF LEAFS ═════════════════════════════════════\n\n    /**\n     * @notice Calculates merkle root for a list of given leafs.\n     * Merkle Tree is constructed by padding the list with ZERO values for leafs until list length is `2**height`.\n     * Merkle Root is calculated for the constructed tree, and then saved in `leafs[0]`.\n     * \u003e Note:\n     * \u003e - `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * \u003e - Caller is expected not to reuse `hashes` list after the call, and only use `leafs[0]` value,\n     * which is guaranteed to contain the calculated merkle root.\n     * \u003e - root is calculated using the `H(0,0) = 0` Merkle Tree implementation. See MerkleTree.sol for details.\n     * @dev Amount of leaves should be at most `2**height`\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param height    Height of the Merkle Tree to construct\n     */\n    function calculateRoot(bytes32[] memory hashes, uint256 height) internal pure {\n        uint256 levelLength = hashes.length;\n        // Amount of hashes could not exceed amount of leafs in tree with the given height\n        if (levelLength \u003e (1 \u003c\u003c height)) revert TreeHeightTooLow();\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\": the amount of iterations for the for loop above.\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n            }\n        }\n    }\n\n    /**\n     * @notice Generates a proof of inclusion of a leaf in the list. If the requested index is outside\n     * of the list range, generates a proof of inclusion for an empty leaf (proof of non-inclusion).\n     * The Merkle Tree is constructed by padding the list with ZERO values until list length is a power of two\n     * __AND__ index is in the extended list range. For example:\n     *  - `hashes.length == 6` and `0 \u003c= index \u003c= 7` will \"extend\" the list to 8 entries.\n     *  - `hashes.length == 6` and `7 \u003c index \u003c= 15` will \"extend\" the list to 16 entries.\n     * \u003e Note: `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * Caller is expected not to reuse `hashes` list after the call.\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param index     Leaf index to generate the proof for\n     * @return proof    Generated merkle proof\n     */\n    function calculateProof(bytes32[] memory hashes, uint256 index) internal pure returns (bytes32[] memory proof) {\n        // Use only meaningful values for the shortened proof\n        // Check if index is within the list range (we want to generates proofs for outside leafs as well)\n        uint256 height = getHeight(index \u003c hashes.length ? hashes.length : (index + 1));\n        proof = new bytes32[](height);\n        uint256 levelLength = hashes.length;\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Use sibling for the merkle proof; `index^1` is index of our sibling\n                proof[h] = (index ^ 1 \u003c levelLength) ? hashes[index ^ 1] : bytes32(0);\n\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\"\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n                // Traverse to parent node\n                index \u003e\u003e= 1;\n            }\n        }\n    }\n\n    /// @notice Returns the height of the tree having a given amount of leafs.\n    function getHeight(uint256 leafs) internal pure returns (uint256 height) {\n        uint256 amount = 1;\n        while (amount \u003c leafs) {\n            unchecked {\n                ++height;\n            }\n            amount \u003c\u003c= 1;\n        }\n    }\n}\n\n// contracts/libs/stack/GasData.sol\n\n/// GasData in encoded data with \"basic information about gas prices\" for some chain.\ntype GasData is uint96;\n\nusing GasDataLib for GasData global;\n\n/// ChainGas is encoded data with given chain's \"basic information about gas prices\".\ntype ChainGas is uint128;\n\nusing GasDataLib for ChainGas global;\n\n/// Library for encoding and decoding GasData and ChainGas structs.\n/// # GasData\n/// `GasData` is a struct to store the \"basic information about gas prices\", that could\n/// be later used to approximate the cost of a message execution, and thus derive the\n/// minimal tip values for sending a message to the chain.\n/// \u003e - `GasData` is supposed to be cached by `GasOracle` contract, allowing to store the\n/// \u003e approximates instead of the exact values, and thus save on storage costs.\n/// \u003e - For instance, if `GasOracle` only updates the values on +- 10% change, having an\n/// \u003e 0.4% error on the approximates would be acceptable.\n/// `GasData` is supposed to be included in the Origin's state, which are synced across\n/// chains using Agent-signed snapshots and attestations.\n/// ## GasData stack layout (from highest bits to lowest)\n///\n/// | Position   | Field        | Type   | Bytes | Description                                         |\n/// | ---------- | ------------ | ------ | ----- | --------------------------------------------------- |\n/// | (012..010] | gasPrice     | uint16 | 2     | Gas price for the chain (in Wei per gas unit)       |\n/// | (010..008] | dataPrice    | uint16 | 2     | Calldata price (in Wei per byte of content)         |\n/// | (008..006] | execBuffer   | uint16 | 2     | Tx fee safety buffer for message execution (in Wei) |\n/// | (006..004] | amortAttCost | uint16 | 2     | Amortized cost for attestation submission (in Wei)  |\n/// | (004..002] | etherPrice   | uint16 | 2     | Chain's Ether Price / Mainnet Ether Price (in BWAD) |\n/// | (002..000] | markup       | uint16 | 2     | Markup for the message execution (in BWAD)          |\n/// \u003e See Number.sol for more details on `Number` type and BWAD (binary WAD) math.\n///\n/// ## ChainGas stack layout (from highest bits to lowest)\n///\n/// | Position   | Field   | Type   | Bytes | Description      |\n/// | ---------- | ------- | ------ | ----- | ---------------- |\n/// | (016..004] | gasData | uint96 | 12    | Chain's gas data |\n/// | (004..000] | domain  | uint32 | 4     | Chain's domain   |\nlibrary GasDataLib {\n    /// @dev Amount of bits to shift to gasPrice field\n    uint96 private constant SHIFT_GAS_PRICE = 10 * 8;\n    /// @dev Amount of bits to shift to dataPrice field\n    uint96 private constant SHIFT_DATA_PRICE = 8 * 8;\n    /// @dev Amount of bits to shift to execBuffer field\n    uint96 private constant SHIFT_EXEC_BUFFER = 6 * 8;\n    /// @dev Amount of bits to shift to amortAttCost field\n    uint96 private constant SHIFT_AMORT_ATT_COST = 4 * 8;\n    /// @dev Amount of bits to shift to etherPrice field\n    uint96 private constant SHIFT_ETHER_PRICE = 2 * 8;\n\n    /// @dev Amount of bits to shift to gasData field\n    uint128 private constant SHIFT_GAS_DATA = 4 * 8;\n\n    // ═════════════════════════════════════════════════ GAS DATA ══════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded GasData struct with the given fields.\n    /// @param gasPrice_        Gas price for the chain (in Wei per gas unit)\n    /// @param dataPrice_       Calldata price (in Wei per byte of content)\n    /// @param execBuffer_      Tx fee safety buffer for message execution (in Wei)\n    /// @param amortAttCost_    Amortized cost for attestation submission (in Wei)\n    /// @param etherPrice_      Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n    /// @param markup_          Markup for the message execution (in BWAD)\n    function encodeGasData(\n        Number gasPrice_,\n        Number dataPrice_,\n        Number execBuffer_,\n        Number amortAttCost_,\n        Number etherPrice_,\n        Number markup_\n    ) internal pure returns (GasData) {\n        // Number type wraps uint16, so could safely be casted to uint96\n        // forgefmt: disable-next-item\n        return GasData.wrap(\n            uint96(Number.unwrap(gasPrice_)) \u003c\u003c SHIFT_GAS_PRICE |\n            uint96(Number.unwrap(dataPrice_)) \u003c\u003c SHIFT_DATA_PRICE |\n            uint96(Number.unwrap(execBuffer_)) \u003c\u003c SHIFT_EXEC_BUFFER |\n            uint96(Number.unwrap(amortAttCost_)) \u003c\u003c SHIFT_AMORT_ATT_COST |\n            uint96(Number.unwrap(etherPrice_)) \u003c\u003c SHIFT_ETHER_PRICE |\n            uint96(Number.unwrap(markup_))\n        );\n    }\n\n    /// @notice Wraps padded uint256 value into GasData struct.\n    function wrapGasData(uint256 paddedGasData) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(paddedGasData));\n    }\n\n    /// @notice Returns the gas price, in Wei per gas unit.\n    function gasPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_GAS_PRICE));\n    }\n\n    /// @notice Returns the calldata price, in Wei per byte of content.\n    function dataPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_DATA_PRICE));\n    }\n\n    /// @notice Returns the tx fee safety buffer for message execution, in Wei.\n    function execBuffer(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_EXEC_BUFFER));\n    }\n\n    /// @notice Returns the amortized cost for attestation submission, in Wei.\n    function amortAttCost(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_AMORT_ATT_COST));\n    }\n\n    /// @notice Returns the ratio of Chain's Ether Price / Mainnet Ether Price, in BWAD math.\n    function etherPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_ETHER_PRICE));\n    }\n\n    /// @notice Returns the markup for the message execution, in BWAD math.\n    function markup(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data)));\n    }\n\n    // ════════════════════════════════════════════════ CHAIN DATA ═════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded ChainGas struct with the given fields.\n    /// @param gasData_ Chain's gas data\n    /// @param domain_  Chain's domain\n    function encodeChainGas(GasData gasData_, uint32 domain_) internal pure returns (ChainGas) {\n        // GasData type wraps uint96, so could safely be casted to uint128\n        return ChainGas.wrap(uint128(GasData.unwrap(gasData_)) \u003c\u003c SHIFT_GAS_DATA | uint128(domain_));\n    }\n\n    /// @notice Wraps padded uint256 value into ChainGas struct.\n    function wrapChainGas(uint256 paddedChainGas) internal pure returns (ChainGas) {\n        // Casting to uint128 will truncate the highest bits, which is the behavior we want\n        return ChainGas.wrap(uint128(paddedChainGas));\n    }\n\n    /// @notice Returns the chain's gas data.\n    function gasData(ChainGas data) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(ChainGas.unwrap(data) \u003e\u003e SHIFT_GAS_DATA));\n    }\n\n    /// @notice Returns the chain's domain.\n    function domain(ChainGas data) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(ChainGas.unwrap(data));\n    }\n\n    /// @notice Returns the hash for the list of ChainGas structs.\n    function snapGasHash(ChainGas[] memory snapGas) internal pure returns (bytes32 snapGasHash_) {\n        // Use assembly to calculate the hash of the array without copying it\n        // ChainGas takes a single word of storage, thus ChainGas[] is stored in the following way:\n        // 0x00: length of the array, in words\n        // 0x20: first ChainGas struct\n        // 0x40: second ChainGas struct\n        // And so on...\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Find the location where the array data starts, we add 0x20 to skip the length field\n            let loc := add(snapGas, 0x20)\n            // Load the length of the array (in words).\n            // Shifting left 5 bits is equivalent to multiplying by 32: this converts from words to bytes.\n            let len := shl(5, mload(snapGas))\n            // Calculate the hash of the array\n            snapGasHash_ := keccak256(loc, len)\n        }\n    }\n}\n\n// contracts/libs/stack/Header.sol\n\n/// Header is encoded data with \"general routing information\".\ntype Header is uint136;\n\nusing HeaderLib for Header global;\n\n/// Types of messages supported by Origin-Destination\n/// - Base: message sent by protocol user, contains tips\n/// - Manager: message sent between AgentManager contracts located on different chains, no tips\nenum MessageFlag {\n    Base,\n    Manager\n}\n\nusing HeaderLib for MessageFlag global;\n\n/// Library for formatting _the header part_ of _the messages used by Origin and Destination_.\n/// - Header represents general information for routing a Message for Origin and Destination.\n/// - Header occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n///\n/// # Header stack layout (from highest bits to lowest)\n///\n/// | Position   | Field            | Type   | Bytes | Description                             |\n/// | ---------- | ---------------- | ------ | ----- | --------------------------------------- |\n/// | (017..016] | flag             | uint8  | 1     | Flag specifying the type of message     |\n/// | (016..012] | origin           | uint32 | 4     | Domain where message originated         |\n/// | (012..008] | nonce            | uint32 | 4     | Message nonce on the origin domain      |\n/// | (008..004] | destination      | uint32 | 4     | Domain where message will be executed   |\n/// | (004..000] | optimisticPeriod | uint32 | 4     | Optimistic period that will be enforced |\nlibrary HeaderLib {\n    /// @dev Amount of bits to shift to flag field\n    uint136 private constant SHIFT_FLAG = 16 * 8;\n    /// @dev Amount of bits to shift to origin field\n    uint136 private constant SHIFT_ORIGIN = 12 * 8;\n    /// @dev Amount of bits to shift to nonce field\n    uint136 private constant SHIFT_NONCE = 8 * 8;\n    /// @dev Amount of bits to shift to destination field\n    uint136 private constant SHIFT_DESTINATION = 4 * 8;\n\n    /// @notice Returns an encoded header with provided fields\n    /// @param origin_              Domain of origin chain\n    /// @param nonce_               Message nonce on origin chain\n    /// @param destination_         Domain of destination chain\n    /// @param optimisticPeriod_    Optimistic period for message execution\n    function encodeHeader(\n        MessageFlag flag_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint32 destination_,\n        uint32 optimisticPeriod_\n    ) internal pure returns (Header) {\n        // All casts below are upcasts, so they are safe\n        // forgefmt: disable-next-item\n        return Header.wrap(\n            uint136(uint8(flag_)) \u003c\u003c SHIFT_FLAG |\n            uint136(origin_) \u003c\u003c SHIFT_ORIGIN |\n            uint136(nonce_) \u003c\u003c SHIFT_NONCE |\n            uint136(destination_) \u003c\u003c SHIFT_DESTINATION |\n            uint136(optimisticPeriod_)\n        );\n    }\n\n    /// @notice Checks that the header is a valid encoded header.\n    function isHeader(uint256 paddedHeader) internal pure returns (bool) {\n        // Check that flag is within range\n        return _flag(paddedHeader) \u003c= uint8(type(MessageFlag).max);\n    }\n\n    /// @notice Wraps the padded encoded request into a Header-typed value.\n    /// @dev The \"padded\" header is simply an encoded header casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded headers\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedHeader) internal pure returns (Header) {\n        // Check that flag is within range\n        if (!isHeader(paddedHeader)) revert FlagOutOfRange();\n        // Casting to uint136 will truncate the highest bits, which is the behavior we want\n        return Header.wrap(uint136(paddedHeader));\n    }\n\n    /// @notice Returns header's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Header header) internal pure returns (bytes32 hashedHeader) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store header in scratch space\n            mstore(0, header)\n            // Compute hash of header padded to 32 bytes\n            hashedHeader := keccak256(0, 32)\n        }\n    }\n\n    // ══════════════════════════════════════════════ HEADER SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns header's flag field\n    function flag(Header header) internal pure returns (MessageFlag) {\n        // We check that flag is within range when wrapping the header, so this cast is safe\n        return MessageFlag(_flag(Header.unwrap(header)));\n    }\n\n    /// @notice Returns header's origin field\n    function origin(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_ORIGIN);\n    }\n\n    /// @notice Returns header's nonce field\n    function nonce(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_NONCE);\n    }\n\n    /// @notice Returns header's destination field\n    function destination(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_DESTINATION);\n    }\n\n    /// @notice Returns header's optimistic seconds field\n    function optimisticPeriod(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns header's flag field without casting to MessageFlag\n    function _flag(uint256 paddedHeader) private pure returns (uint8) {\n        // Casting to uint8 will truncate the highest bits, which is the behavior we want\n        return uint8(paddedHeader \u003e\u003e SHIFT_FLAG);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n     * constructor.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall \u0026\u0026 _initialized \u003c 1) || (!AddressUpgradeable.isContract(address(this)) \u0026\u0026 _initialized == 1),\n            \"Initializable: contract is already initialized\"\n        );\n        _initialized = 1;\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: setting the version to 255 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing \u0026\u0026 _initialized \u003c version, \"Initializable: contract is already initialized\");\n        _initialized = version;\n        _initializing = true;\n        _;\n        _initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        require(_initializing, \"Initializable: contract is not initializing\");\n        _;\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized != type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint8) {\n        return _initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _initializing;\n    }\n}\n\n// contracts/interfaces/IAgentManager.sol\n\ninterface IAgentManager {\n    /**\n     * @notice Allows Inbox to open a Dispute between a Guard and a Notary, if they are both not in Dispute already.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Guard or Notary is already in Dispute.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Allows Inbox to slash an agent, if their fraud was proven.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Domain doesn't match the saved agent domain.\n     * @param domain    Domain where the Agent is active\n     * @param agent     Address of the Agent\n     * @param prover    Address that initially provided fraud proof\n     */\n    function slashAgent(uint32 domain, address agent, address prover) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest known root of the Agent Merkle Tree.\n     */\n    function agentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns the number of opened Disputes.\n     * @dev This includes the Disputes that have been resolved already.\n     */\n    function getDisputesAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns information about the dispute with the given index.\n     * @dev Will revert if dispute with given index hasn't been opened yet.\n     * @param index             Dispute index\n     * @return guard            Address of the Guard in the Dispute\n     * @return notary           Address of the Notary in the Dispute\n     * @return slashedAgent     Address of the Agent who was slashed when Dispute was resolved\n     * @return fraudProver      Address who provided fraud proof to resolve the Dispute\n     * @return reportPayload    Raw payload with report data that led to the Dispute\n     * @return reportSignature  Guard signature for the report payload\n     */\n    function getDispute(uint256 index)\n        external\n        view\n        returns (\n            address guard,\n            address notary,\n            address slashedAgent,\n            address fraudProver,\n            bytes memory reportPayload,\n            bytes memory reportSignature\n        );\n\n    /**\n     * @notice Returns the current Dispute status of a given agent. See Structures.sol for details.\n     * @dev Every returned value will be set to zero if agent was not slashed and is not in Dispute.\n     * `rival` and `disputePtr` will be set to zero if the agent was slashed without being in Dispute.\n     * @param agent         Agent address\n     * @return flag         Flag describing the current Dispute status for the agent: None/Pending/Slashed\n     * @return rival        Address of the rival agent in the Dispute\n     * @return fraudProver  Address who provided fraud proof to resolve the Dispute\n     * @return disputePtr   Index of the opened Dispute PLUS ONE. Zero if agent is not in Dispute.\n     */\n    function disputeStatus(address agent)\n        external\n        view\n        returns (DisputeFlag flag, address rival, address fraudProver, uint256 disputePtr);\n}\n\n// contracts/interfaces/IAgentSecured.sol\n\ninterface IAgentSecured {\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * between a Guard and a Notary has been opened.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * has been resolved due to one of the agents being slashed.\n     * \u003e `rivalIndex` will be ZERO, if the slashed agent was not in the Dispute.\n     * @param slashedIndex  Index of the slashed agent in the Agent Merkle Tree\n     * @param rivalIndex    Index of the their Dispute Rival in the Agent Merkle Tree\n     */\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the address of the local AgentManager contract, which is treated as\n     * the \"source of truth\" for agent statuses.\n     */\n    function agentManager() external view returns (address);\n\n    /**\n     * @notice Returns the address of the local Inbox contract, which is treated as\n     * the \"source of truth\" for agent-signed statements.\n     * @dev Inbox passes verified agent statements to `IAgentSecured` contract.\n     */\n    function inbox() external view returns (address);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns (flag, openedAt, resolvedAt) that describes the latest status of\n     * the latest dispute for an agent with a given index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param agentIndex    Agent index in the Agent Merkle Tree\n     * @return              Latest dispute status for the given agent: (flag, openedAt, resolvedAt)\n     */\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory);\n}\n\n// contracts/libs/memory/ByteString.sol\n\n/// @dev CallData is a memory view over the payload to be used for an external call, i.e.\n/// recipient.call(callData). Its length is always (4 + 32 * N) bytes:\n/// - First 4 bytes represent the function selector.\n/// - 32 * N bytes represent N words that function arguments occupy.\ntype CallData is uint256;\n\n/// @dev Attach library functions to CallData\nusing ByteString for CallData global;\n\n/// @dev Signature is a memory view over a \"65 bytes\" array representing a ECDSA signature.\ntype Signature is uint256;\n\n/// @dev Attach library functions to Signature\nusing ByteString for Signature global;\n\nlibrary ByteString {\n    using MemViewLib for bytes;\n\n    /**\n     * @dev non-compact ECDSA signatures are enforced as of OZ 4.7.3\n     *\n     *      Signature payload memory layout\n     * [000 .. 032) r   bytes32 32 bytes\n     * [032 .. 064) s   bytes32 32 bytes\n     * [064 .. 065) v   uint8    1 byte\n     */\n    uint256 internal constant SIGNATURE_LENGTH = 65;\n    uint256 private constant OFFSET_R = 0;\n    uint256 private constant OFFSET_S = 32;\n    uint256 private constant OFFSET_V = 64;\n\n    /**\n     * @dev Calldata memory layout\n     * [000 .. 004) selector    bytes4  4 bytes\n     *      Optional: N function arguments\n     * [004 .. 036) arg1        bytes32 32 bytes\n     *      ..\n     * [AAA .. END) argN        bytes32 32 bytes\n     */\n    uint256 internal constant SELECTOR_LENGTH = 4;\n    uint256 private constant OFFSET_SELECTOR = 0;\n    uint256 private constant OFFSET_ARGUMENTS = SELECTOR_LENGTH;\n\n    // ═════════════════════════════════════════════════ SIGNATURE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the signature payload from the given values.\n     * @dev Using ByteString.formatSignature({r: r, s: s, v: v}) will make sure\n     * that params are given in the right order.\n     */\n    function formatSignature(bytes32 r, bytes32 s, uint8 v) internal pure returns (bytes memory) {\n        return abi.encodePacked(r, s, v);\n    }\n\n    /**\n     * @notice Returns a Signature view over for the given payload.\n     * @dev Will revert if the payload is not a signature.\n     */\n    function castToSignature(bytes memory payload) internal pure returns (Signature) {\n        return castToSignature(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Signature view.\n     * @dev Will revert if the memory view is not over a signature.\n     */\n    function castToSignature(MemView memView) internal pure returns (Signature) {\n        if (!isSignature(memView)) revert UnformattedSignature();\n        return Signature.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a signature\n     */\n    function isSignature(MemView memView) internal pure returns (bool) {\n        return memView.len() == SIGNATURE_LENGTH;\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Signature signature) internal pure returns (MemView) {\n        return MemView.wrap(Signature.unwrap(signature));\n    }\n\n    // ═════════════════════════════════════════════ SIGNATURE SLICING ═════════════════════════════════════════════════\n\n    /// @notice Unpacks signature payload into (r, s, v) parameters.\n    /// @dev Make sure to verify signature length with isSignature() beforehand.\n    function toRSV(Signature signature) internal pure returns (bytes32 r, bytes32 s, uint8 v) {\n        // Get the underlying memory view\n        MemView memView = unwrap(signature);\n        r = memView.index({index_: OFFSET_R, bytes_: 32});\n        s = memView.index({index_: OFFSET_S, bytes_: 32});\n        // Can be safely casted to uint8, since we index a single byte\n        v = uint8(memView.indexUint({index_: OFFSET_V, bytes_: 1}));\n    }\n\n    // ═════════════════════════════════════════════════ CALLDATA ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the calldata with the modified arguments:\n     * the existing arguments are prepended with the arguments from the prefix.\n     * @dev Given:\n     *  - `calldata = abi.encodeWithSelector(foo.selector, d, e);`\n     *  - `prefix = abi.encode(a, b, c);`\n     *  - `a`, `b`, `c` are arguments of static type (i.e. not dynamically sized ones)\n     *      Then:\n     *  - Function will return abi.encodeWithSelector(foo.selector, a, c, c, d, e)\n     *  - Returned calldata will trigger `foo(a, b, c, d, e)` when used for a contract call.\n     * Note: for clarification as to what types are considered static, see\n     * https://docs.soliditylang.org/en/latest/abi-spec.html#formal-specification-of-the-encoding\n     * @param callData  Calldata that needs to be modified\n     * @param prefix    ABI-encoded arguments to use as the first arguments in the new calldata\n     * @return Modified calldata having prefix as the first arguments.\n     */\n    function addPrefix(CallData callData, bytes memory prefix) internal view returns (bytes memory) {\n        // Prefix should occupy a whole amount of words in memory\n        if (!_fullWords(prefix.length)) revert UnformattedCallDataPrefix();\n        MemView[] memory views = new MemView[](3);\n        // Use payload's function selector\n        views[0] = abi.encodePacked(callData.callSelector()).ref();\n        // Use prefix as the first arguments\n        views[1] = prefix.ref();\n        // Use payload's remaining arguments\n        views[2] = callData.arguments();\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a CallData view over for the given payload.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(bytes memory payload) internal pure returns (CallData) {\n        return castToCallData(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a CallData view.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(MemView memView) internal pure returns (CallData) {\n        if (!isCallData(memView)) revert UnformattedCallData();\n        return CallData.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a valid calldata, i.e.\n     * a function selector, followed by arbitrary amount of arguments.\n     */\n    function isCallData(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Calldata should at least have a function selector\n        if (length \u003c SELECTOR_LENGTH) return false;\n        // The remainder of the calldata should be exactly N memory words (N \u003e= 0)\n        return _fullWords(length - SELECTOR_LENGTH);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(CallData callData) internal pure returns (MemView) {\n        return MemView.wrap(CallData.unwrap(callData));\n    }\n\n    /// @notice Returns callData's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(CallData callData) internal pure returns (bytes32) {\n        return callData.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ CALLDATA SLICING ══════════════════════════════════════════════════\n\n    /**\n     * @notice Returns amount of memory words (32 byte chunks) the function arguments\n     * occupy in the calldata.\n     * @dev This might differ from amount of arguments supplied, if any of the arguments\n     * occupies more than one memory slot. It is true, however, that argument part of the payload\n     * occupies exactly N words, even for dynamic types like `bytes`\n     */\n    function argumentWords(CallData callData) internal pure returns (uint256) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        // Equivalent of (length - SELECTOR_LENGTH) / 32\n        return (memView.len() - SELECTOR_LENGTH) \u003e\u003e 5;\n    }\n\n    /// @notice Returns selector for the provided calldata.\n    function callSelector(CallData callData) internal pure returns (bytes4) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return bytes4(memView.index({index_: OFFSET_SELECTOR, bytes_: SELECTOR_LENGTH}));\n    }\n\n    /// @notice Returns abi encoded arguments for the provided calldata.\n    function arguments(CallData callData) internal pure returns (MemView) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return memView.sliceFrom({index_: OFFSET_ARGUMENTS});\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if length is full amount of memory words (32 bytes).\n    function _fullWords(uint256 length) internal pure returns (bool) {\n        // The equivalent of length % 32 == 0\n        return length \u0026 31 == 0;\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n    function __Context_init() internal onlyInitializing {\n    }\n\n    function __Context_init_unchained() internal onlyInitializing {\n    }\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[50] private __gap;\n}\n\n// contracts/libs/merkle/MerkleTree.sol\n\n/// `BaseTree` is a struct representing incremental merkle tree.\n/// - Contains only the current branch.\n/// - The number of inserted leaves is stored externally, and is later supplied for tree operations.\n/// - Has a fixed height of `ORIGIN_TREE_HEIGHT`.\n/// - Can store up to `2 ** ORIGIN_TREE_HEIGHT - 1` leaves.\n/// \u003e Note: the hash function for the tree `H(x, y)` is defined as:\n/// \u003e - `H(0,0) = 0`\n/// \u003e - `H(x,y) = keccak256(x, y), when (x != 0 || y != 0)`\n/// ## Invariant for leafs\n/// - The leftmost empty leaf has `index == count`, where `count` is the amount of the inserted leafs so far.\n/// - Value for any empty leaf or node is bytes32(0).\n/// ## Invariant for current branch\n/// `branch[i]` is always the value of a node on the i-th level.\n/// Levels are numbered from leafs to root: `0 .. ORIGIN_TREE_HEIGHT`.\n/// `branch[i]` stores the value for the node, such that:\n//  - The node is a \"left child\" (e.g. has an even index).\n/// - The node must have two non-empty children.\n/// - Out of all level's \"left child\" nodes with \"non-empty children\",\n/// the one with the biggest index (the rightmost one) is stored as `branch[i]`.\n/// \u003e __`branch` could be used to form a proof of inclusion for the first empty leaf (`index == count`).__\n/// _Here is how:_\n/// - Let's walk along the path from the \"first empty leaf\" to the root.\n/// - i-th bit of the \"first empty leaf\" index (which is equal to `count`) determines if the path's node\n/// for this i-th level is a \"left child\" or a \"right child\".\n/// - i-th bit in `count` is 0 → we are the left child on this level → sibling is the right child\n/// that does not exist yet → `proof[i] = bytes32(0)`.\n/// - i-th bit in `count` is 1 → we are the right child on this level → sibling is the left child\n/// sibling is the rightmost \"left child\" node on the level → `proof[i] = branch[i]`.\n/// \u003e Therefore `proof[i] = (count \u0026 (1 \u003c\u003c i)) == 0 ? bytes32(0) : branch[i])`\nstruct BaseTree {\n    bytes32[ORIGIN_TREE_HEIGHT] branch;\n}\n\nusing MerkleTree for BaseTree global;\n\n/// `HistoricalTree` is an incremental merkle tree keeping track of its historical merkle roots.\n/// \u003e - `roots[N]` is the root of the tree after `N` leafs were inserted\n/// \u003e - `roots[0] == bytes32(0)`\n/// @param tree     Incremental merkle tree\n/// @param roots    Historical merkle roots of the tree\nstruct HistoricalTree {\n    BaseTree tree;\n    bytes32[] roots;\n}\n\nusing MerkleTree for HistoricalTree global;\n\n/// `DynamicTree` is a struct representing a Merkle Tree with `2**AGENT_TREE_HEIGHT` leaves.\n/// - A single operation is available: update value for leaf with an arbitrary index (which might be a non-empty leaf).\n/// - This is done by requesting the proof of inclusion for the old value, which is used to both\n/// verify the old value, and calculate the new root.\n/// \u003e Based on Original idea from [ER forum post](https://ethresear.ch/t/efficient-on-chain-dynamic-merkle-tree/11054).\nstruct DynamicTree {\n    bytes32 root;\n}\n\nusing MerkleTree for DynamicTree global;\n\n/// MerkleTree is work based on Nomad's Merkle.sol, which is used under MIT OR Apache-2.0\n/// [link](https://github.com/nomad-xyz/monorepo/blob/main/packages/contracts-core/contracts/libs/Merkle.sol).\n/// With the following changes:\n/// - Adapted for Solidity 0.8.x.\n/// - Amount of tree leaves stored externally.\n/// - Added thorough documentation.\n/// - `H(0,0) = 0` optimization from [ER forum post](https://ethresear.ch/t/optimizing-sparse-merkle-trees/3751/6).\n/// \u003e Nomad's Merkle.sol is work based on eth2 deposit contract, which is used under CC0-1.0\n///[link](https://github.com/ethereum/deposit_contract/blob/dev/deposit_contract/contracts/validator_registration.v.py).\n/// With the following changes:\n/// \u003e - Implemented in Solidity 0.7.6 (eth2 deposit contract implemented in Vyper).\n/// \u003e - `H() = keccak256()` is used as the hashing function instead of `sha256()`.\nlibrary MerkleTree {\n    /// @dev For root calculation we need at least one empty leaf, thus the minus one in the formula.\n    uint256 internal constant MAX_LEAVES = 2 ** ORIGIN_TREE_HEIGHT - 1;\n\n    // ═════════════════════════════════════════════════ BASE TREE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Inserts `node` into merkle tree\n     * @dev Reverts if tree is full\n     * @param newCount  Amount of inserted leaves in the tree after the insertion (i.e. current + 1)\n     * @param node      Element to insert into tree\n     */\n    function insertBase(BaseTree storage tree, uint256 newCount, bytes32 node) internal {\n        if (newCount \u003e MAX_LEAVES) revert MerkleTreeFull();\n        // We go up the tree following the branch from the empty leaf AFTER the just inserted one.\n        // We stop when we find the first \"right child\" node.\n        // Its sibling is now the rightmost \"left child\" node that has two non-empty children.\n        // Therefore we need to update `tree.branch` value on this level.\n        // One could see that `tree.branch` value on lower and higher levels remain unchanged.\n\n        // Loop invariant: `node` is the current level's value for the branch from JUST INSERTED leaf\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            if ((newCount \u0026 1) == 1) {\n                // Found the first \"right child\" node on the branch from EMPTY leaf\n                // `node` is the value for node on branch from JUST INSERTED leaf\n                // Which in this case is the \"left child\".\n                // We update tree.branch and exit\n                tree.branch[i] = node;\n                return;\n            }\n            // On the branch from EMPTY leaf this is still a \"left child\".\n            // Meaning on branch from JUST INSERTED leaf, `node` is a right child.\n            // We compute value for `node` parent using `tree.branch` invariant:\n            // This is the rightmost \"left child\" node, which would be sibling of `node`.\n            node = MerkleMath.getParent(tree.branch[i], node);\n            // Get the parent index, and go to the next tree level\n            newCount \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n        // As the loop should always end prematurely with the `return` statement,\n        // this code should be unreachable. We assert `false` just to be safe.\n        assert(false);\n    }\n\n    /**\n     * @notice Calculates and returns current root of the merkle tree.\n     * @param count     Current amount of inserted leaves in the tree\n     * @return current  Calculated root of `tree`\n     */\n    function rootBase(BaseTree storage tree, uint256 count) internal view returns (bytes32 current) {\n        // To calculate the root we follow the branch of first EMPTY leaf (index == count)\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            // Check if we are the left or the right child on the current level\n            if ((count \u0026 1) == 1) {\n                // We are the right child. Our sibling is the \"rightmost\" \"left-child\" node\n                // that has two non-empty children → sibling is `tree.branch[i]`\n                current = MerkleMath.getParent(tree.branch[i], current);\n            } else {\n                // We are the left child. Our sibling does not exist yet → sibling is EMPTY\n                current = MerkleMath.getParent(current, bytes32(0));\n            }\n            // Get the parent index, and go to the next tree level\n            count \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    // ══════════════════════════════════════════════ HISTORICAL TREE ══════════════════════════════════════════════════\n\n    /// @notice Initializes the historical roots for the tree by inserting an empty root.\n    // solhint-disable-next-line ordering\n    function initializeRoots(HistoricalTree storage tree) internal returns (bytes32 savedRoot) {\n        // This should only be called once, when the contract is initialized\n        assert(tree.roots.length == 0);\n        // Save root for empty merkle tree: bytes32(0)\n        tree.roots.push(savedRoot);\n    }\n\n    /// @notice Inserts a new leaf into the merkle tree.\n    /// @dev Reverts if tree is full.\n    /// @param node         Element to insert into tree\n    /// @return newRoot     Merkle root after the leaf was inserted\n    function insert(HistoricalTree storage tree, bytes32 node) internal returns (bytes32 newRoot) {\n        // Tree count after the new leaf will be inserted (we store roots[0] as root of empty tree)\n        uint256 newCount = tree.roots.length;\n        tree.tree.insertBase(newCount, node);\n        // Save the new root\n        newRoot = tree.tree.rootBase(newCount);\n        tree.roots.push(newRoot);\n    }\n\n    /// @notice Returns the historical root of the merkle tree.\n    /// @dev Reverts if not enough leafs have been inserted.\n    /// @param count            Amount of leafs in the tree at some point of time\n    /// @return historicalRoot  Merkle root after `count` leafs were inserted\n    function root(HistoricalTree storage tree, uint256 count) internal view returns (bytes32 historicalRoot) {\n        if (count \u003e= tree.roots.length) revert NotEnoughLeafs();\n        return tree.roots[count];\n    }\n\n    // ═══════════════════════════════════════════════ DYNAMIC TREE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Updates the value for the leaf with the given index in the Dynamic Merkle Tree.\n     * @dev Will revert if incorrect proof of inclusion for old value is supplied.\n     * @param tree          Dynamic merkle tree\n     * @param index         Index of the leaf to update\n     * @param oldValue      Previous value of the leaf\n     * @param branch        Proof of inclusion of previous value into the tree\n     * @param newValue      New leaf value to assign\n     * @return newRoot      New value for the Merkle Root after the leaf is updated\n     */\n    function update(\n        DynamicTree storage tree,\n        uint256 index,\n        bytes32 oldValue,\n        bytes32[] memory branch,\n        bytes32 newValue\n    ) internal returns (bytes32 newRoot) {\n        // Check that the old value + proof result in a correct root\n        if (MerkleMath.proofRoot(index, oldValue, branch, AGENT_TREE_HEIGHT) != tree.root) {\n            revert LeafNotProven();\n        }\n        // New root is new value + the same proof (values for sibling nodes are not updated)\n        newRoot = MerkleMath.proofRoot(index, newValue, branch, AGENT_TREE_HEIGHT);\n        // Write the new root\n        tree.root = newRoot;\n    }\n}\n\n// contracts/libs/stack/Tips.sol\n\n/// Tips is encoded data with \"tips paid for sending a base message\".\n/// Note: even though uint256 is also an underlying type for MemView, Tips is stored ON STACK.\ntype Tips is uint256;\n\nusing TipsLib for Tips global;\n\n/// # Tips\n/// Library for formatting _the tips part_ of _the base messages_.\n///\n/// ## How the tips are awarded\n/// Tips are paid for sending a base message, and are split across all the agents that\n/// made the message execution on destination chain possible.\n/// ### Summit tips\n/// Split between:\n///     - Guard posting a snapshot with state ST_G for the origin chain.\n///     - Notary posting a snapshot SN_N using ST_G. This creates attestation A.\n///     - Notary posting a message receipt after it is executed on destination chain.\n/// ### Attestation tips\n/// Paid to:\n///     - Notary posting attestation A to destination chain.\n/// ### Execution tips\n/// Paid to:\n///     - First executor performing a valid execution attempt (correct proofs, optimistic period over),\n///      using attestation A to prove message inclusion on origin chain, whether the recipient reverted or not.\n/// ### Delivery tips.\n/// Paid to:\n///     - Executor who successfully executed the message on destination chain.\n///\n/// ## Tips encoding\n/// - Tips occupy a single storage word, and thus are stored on stack instead of being stored in memory.\n/// - The actual tip values should be determined by multiplying stored values by divided by TIPS_MULTIPLIER=2**32.\n/// - Tips are packed into a single word of storage, while allowing real values up to ~8*10**28 for every tip category.\n/// \u003e The only downside is that the \"real tip values\" are now multiplies of ~4*10**9, which should be fine even for\n/// the chains with the most expensive gas currency.\n/// # Tips stack layout (from highest bits to lowest)\n///\n/// | Position   | Field          | Type   | Bytes | Description                                                |\n/// | ---------- | -------------- | ------ | ----- | ---------------------------------------------------------- |\n/// | (032..024] | summitTip      | uint64 | 8     | Tip for agents interacting with Summit contract            |\n/// | (024..016] | attestationTip | uint64 | 8     | Tip for Notary posting attestation to Destination contract |\n/// | (016..008] | executionTip   | uint64 | 8     | Tip for valid execution attempt on destination chain       |\n/// | (008..000] | deliveryTip    | uint64 | 8     | Tip for successful message delivery on destination chain   |\n\nlibrary TipsLib {\n    using SafeCast for uint256;\n\n    /// @dev Amount of bits to shift to summitTip field\n    uint256 private constant SHIFT_SUMMIT_TIP = 24 * 8;\n    /// @dev Amount of bits to shift to attestationTip field\n    uint256 private constant SHIFT_ATTESTATION_TIP = 16 * 8;\n    /// @dev Amount of bits to shift to executionTip field\n    uint256 private constant SHIFT_EXECUTION_TIP = 8 * 8;\n\n    // ═══════════════════════════════════════════════════ TIPS ════════════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips with the given fields\n    /// @param summitTip_        Tip for agents interacting with Summit contract, divided by TIPS_MULTIPLIER\n    /// @param attestationTip_   Tip for Notary posting attestation to Destination contract, divided by TIPS_MULTIPLIER\n    /// @param executionTip_     Tip for valid execution attempt on destination chain, divided by TIPS_MULTIPLIER\n    /// @param deliveryTip_      Tip for successful message delivery on destination chain, divided by TIPS_MULTIPLIER\n    function encodeTips(uint64 summitTip_, uint64 attestationTip_, uint64 executionTip_, uint64 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // forgefmt: disable-next-item\n        return Tips.wrap(\n            uint256(summitTip_) \u003c\u003c SHIFT_SUMMIT_TIP |\n            uint256(attestationTip_) \u003c\u003c SHIFT_ATTESTATION_TIP |\n            uint256(executionTip_) \u003c\u003c SHIFT_EXECUTION_TIP |\n            uint256(deliveryTip_)\n        );\n    }\n\n    /// @notice Convenience function to encode tips with uint256 values.\n    function encodeTips256(uint256 summitTip_, uint256 attestationTip_, uint256 executionTip_, uint256 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // In practice, the tips amounts are not supposed to be higher than 2**96, and with 32 bits of granularity\n        // using uint64 is enough to store the values. However, we still check for overflow just in case.\n        // TODO: consider using Number type to store the tips values.\n        return encodeTips({\n            summitTip_: (summitTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            attestationTip_: (attestationTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            executionTip_: (executionTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            deliveryTip_: (deliveryTip_ \u003e\u003e TIPS_GRANULARITY).toUint64()\n        });\n    }\n\n    /// @notice Wraps the padded encoded tips into a Tips-typed value.\n    /// @dev There is no actual padding here, as the underlying type is already uint256,\n    /// but we include this function for consistency and to be future-proof, if tips will eventually use anything\n    /// smaller than uint256.\n    function wrapPadded(uint256 paddedTips) internal pure returns (Tips) {\n        return Tips.wrap(paddedTips);\n    }\n\n    /**\n     * @notice Returns a formatted Tips payload specifying empty tips.\n     * @return Formatted tips\n     */\n    function emptyTips() internal pure returns (Tips) {\n        return Tips.wrap(0);\n    }\n\n    /// @notice Returns tips's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Tips tips) internal pure returns (bytes32 hashedTips) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store tips in scratch space\n            mstore(0, tips)\n            // Compute hash of tips padded to 32 bytes\n            hashedTips := keccak256(0, 32)\n        }\n    }\n\n    // ═══════════════════════════════════════════════ TIPS SLICING ════════════════════════════════════════════════════\n\n    /// @notice Returns summitTip field\n    function summitTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_SUMMIT_TIP);\n    }\n\n    /// @notice Returns attestationTip field\n    function attestationTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_ATTESTATION_TIP);\n    }\n\n    /// @notice Returns executionTip field\n    function executionTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_EXECUTION_TIP);\n    }\n\n    /// @notice Returns deliveryTip field\n    function deliveryTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips));\n    }\n\n    // ════════════════════════════════════════════════ TIPS VALUE ═════════════════════════════════════════════════════\n\n    /// @notice Returns total value of the tips payload.\n    /// This is the sum of the encoded values, scaled up by TIPS_MULTIPLIER\n    function value(Tips tips) internal pure returns (uint256 value_) {\n        value_ = uint256(tips.summitTip()) + tips.attestationTip() + tips.executionTip() + tips.deliveryTip();\n        value_ \u003c\u003c= TIPS_GRANULARITY;\n    }\n\n    /// @notice Increases the delivery tip to match the new value.\n    function matchValue(Tips tips, uint256 newValue) internal pure returns (Tips newTips) {\n        uint256 oldValue = tips.value();\n        if (newValue \u003c oldValue) revert TipsValueTooLow();\n        // We want to increase the delivery tip, while keeping the other tips the same\n        unchecked {\n            uint256 delta = (newValue - oldValue) \u003e\u003e TIPS_GRANULARITY;\n            // `delta` fits into uint224, as TIPS_GRANULARITY is 32, so this never overflows uint256.\n            // In practice, this will never overflow uint64 as well, but we still check it just in case.\n            if (delta + tips.deliveryTip() \u003e type(uint64).max) revert TipsOverflow();\n            // Delivery tips occupy lowest 8 bytes, so we can just add delta to the tips value\n            // to effectively increase the delivery tip (knowing that delta fits into uint64).\n            newTips = Tips.wrap(Tips.unwrap(tips) + delta);\n        }\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    function __Ownable_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable_init_unchained() internal onlyInitializing {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n    function __Ownable2Step_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable2Step_init_unchained() internal onlyInitializing {\n    }\n    address private _pendingOwner;\n\n    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Returns the address of the pending owner.\n     */\n    function pendingOwner() public view virtual returns (address) {\n        return _pendingOwner;\n    }\n\n    /**\n     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual override onlyOwner {\n        _pendingOwner = newOwner;\n        emit OwnershipTransferStarted(owner(), newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual override {\n        delete _pendingOwner;\n        super._transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev The new owner accepts the ownership transfer.\n     */\n    function acceptOwnership() public virtual {\n        address sender = _msgSender();\n        require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n        _transferOwnership(sender);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// contracts/libs/memory/State.sol\n\n/// State is a memory view over a formatted state payload.\ntype State is uint256;\n\nusing StateLib for State global;\n\n/// # State\n/// State structure represents the state of Origin contract at some point of time.\n/// - State is structured in a way to track the updates of the Origin Merkle Tree.\n/// - State includes root of the Origin Merkle Tree, origin domain and some additional metadata.\n/// ## Origin Merkle Tree\n/// Hash of every sent message is inserted in the Origin Merkle Tree, which changes\n/// the value of Origin Merkle Root (which is the root for the mentioned tree).\n/// - Origin has a single Merkle Tree for all messages, regardless of their destination domain.\n/// - This leads to Origin state being updated if and only if a message was sent in a block.\n/// - Origin contract is a \"source of truth\" for states: a state is considered \"valid\" in its Origin,\n/// if it matches the state of the Origin contract after the N-th (nonce) message was sent.\n///\n/// # Memory layout of State fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                    |\n/// | ---------- | ----------- | ------- | ----- | ------------------------------ |\n/// | [000..032) | root        | bytes32 | 32    | Root of the Origin Merkle Tree |\n/// | [032..036) | origin      | uint32  | 4     | Domain where Origin is located |\n/// | [036..040) | nonce       | uint32  | 4     | Amount of sent messages        |\n/// | [040..045) | blockNumber | uint40  | 5     | Block of last sent message     |\n/// | [045..050) | timestamp   | uint40  | 5     | Time of last sent message      |\n/// | [050..062) | gasData     | uint96  | 12    | Gas data for the chain         |\n///\n/// @dev State could be used to form a Snapshot to be signed by a Guard or a Notary.\nlibrary StateLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_ROOT = 0;\n    uint256 private constant OFFSET_ORIGIN = 32;\n    uint256 private constant OFFSET_NONCE = 36;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 40;\n    uint256 private constant OFFSET_TIMESTAMP = 45;\n    uint256 private constant OFFSET_GAS_DATA = 50;\n\n    // ═══════════════════════════════════════════════════ STATE ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted State payload with provided fields\n     * @param root_         New merkle root\n     * @param origin_       Domain of Origin's chain\n     * @param nonce_        Nonce of the merkle root\n     * @param blockNumber_  Block number when root was saved in Origin\n     * @param timestamp_    Block timestamp when root was saved in Origin\n     * @param gasData_      Gas data for the chain\n     * @return Formatted state\n     */\n    function formatState(\n        bytes32 root_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_,\n        GasData gasData_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(root_, origin_, nonce_, blockNumber_, timestamp_, gasData_);\n    }\n\n    /**\n     * @notice Returns a State view over the given payload.\n     * @dev Will revert if the payload is not a state.\n     */\n    function castToState(bytes memory payload) internal pure returns (State) {\n        return castToState(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a State view.\n     * @dev Will revert if the memory view is not over a state.\n     */\n    function castToState(MemView memView) internal pure returns (State) {\n        if (!isState(memView)) revert UnformattedState();\n        return State.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted State.\n    function isState(MemView memView) internal pure returns (bool) {\n        return memView.len() == STATE_LENGTH;\n    }\n\n    /// @notice Returns the hash of a State, that could be later signed by a Guard to signal\n    /// that the state is invalid.\n    function hashInvalid(State state) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(stateInvalidSalt, keccak(state))\n        return state.unwrap().keccakSalted(STATE_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(State state) internal pure returns (MemView) {\n        return MemView.wrap(State.unwrap(state));\n    }\n\n    /// @notice Compares two State structures.\n    function equals(State a, State b) internal pure returns (bool) {\n        // Length of a State payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═══════════════════════════════════════════════ STATE HASHING ═══════════════════════════════════════════════════\n\n    /// @notice Returns the hash of the State.\n    /// @dev We are using the Merkle Root of a tree with two leafs (see below) as state hash.\n    function leaf(State state) internal pure returns (bytes32) {\n        (bytes32 leftLeaf_, bytes32 rightLeaf_) = state.subLeafs();\n        // Final hash is the parent of these leafs\n        return keccak256(bytes.concat(leftLeaf_, rightLeaf_));\n    }\n\n    /// @notice Returns \"sub-leafs\" of the State. Hash of these \"sub leafs\" is going to be used\n    /// as a \"state leaf\" in the \"Snapshot Merkle Tree\".\n    /// This enables proving that leftLeaf = (root, origin) was a part of the \"Snapshot Merkle Tree\",\n    /// by combining `rightLeaf` with the remainder of the \"Snapshot Merkle Proof\".\n    function subLeafs(State state) internal pure returns (bytes32 leftLeaf_, bytes32 rightLeaf_) {\n        MemView memView = state.unwrap();\n        // Left leaf is (root, origin)\n        leftLeaf_ = memView.prefix({len_: OFFSET_NONCE}).keccak();\n        // Right leaf is (metadata), or (nonce, blockNumber, timestamp)\n        rightLeaf_ = memView.sliceFrom({index_: OFFSET_NONCE}).keccak();\n    }\n\n    /// @notice Returns the left \"sub-leaf\" of the State.\n    function leftLeaf(bytes32 root_, uint32 origin_) internal pure returns (bytes32) {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(root_, origin_));\n    }\n\n    /// @notice Returns the right \"sub-leaf\" of the State.\n    function rightLeaf(uint32 nonce_, uint40 blockNumber_, uint40 timestamp_, GasData gasData_)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(nonce_, blockNumber_, timestamp_, gasData_));\n    }\n\n    // ═══════════════════════════════════════════════ STATE SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns a historical Merkle root from the Origin contract.\n    function root(State state) internal pure returns (bytes32) {\n        return state.unwrap().index({index_: OFFSET_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns domain of chain where the Origin contract is deployed.\n    function origin(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns nonce of Origin contract at the time, when `root` was the Merkle root.\n    function nonce(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when `root` was saved in Origin.\n    function blockNumber(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when `root` was saved in Origin.\n    /// @dev This is the timestamp according to the origin chain.\n    function timestamp(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n\n    /// @notice Returns gas data for the chain.\n    function gasData(State state) internal pure returns (GasData) {\n        return GasDataLib.wrapGasData(state.unwrap().indexUint({index_: OFFSET_GAS_DATA, bytes_: GAS_DATA_LENGTH}));\n    }\n}\n\n// contracts/libs/memory/BaseMessage.sol\n\n/// BaseMessage is a memory view over the base message supported by Origin-Destination\ntype BaseMessage is uint256;\n\nusing BaseMessageLib for BaseMessage global;\n\n/// BaseMessage structure represents a base message sent via the Origin-Destination contracts.\n/// - It only contains data relevant to the base message, the rest of data is encoded in the message header.\n/// - `sender` and `recipient` for EVM chains are EVM addresses casted to bytes32, while preserving left-alignment.\n/// - `tips` and `request` parameters are specified by a message sender\n/// \u003e Origin will calculate minimum tips for given request and content length, and will reject messages with tips\n/// lower than that.\n///\n/// # Memory layout of BaseMessage fields\n///\n/// | Position   | Field     | Type    | Bytes | Description                            |\n/// | ---------- | --------- | ------- | ----- | -------------------------------------- |\n/// | [000..032) | tips      | uint256 | 32    | Encoded tips paid on origin chain      |\n/// | [032..064) | sender    | bytes32 | 32    | Sender address on origin chain         |\n/// | [064..096) | recipient | bytes32 | 32    | Recipient address on destination chain |\n/// | [096..116) | request   | uint160 | 20    | Encoded request for message execution  |\n/// | [104..AAA) | content   | bytes   | ??    | Content to be passed to recipient      |\nlibrary BaseMessageLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_TIPS = 0;\n    uint256 private constant OFFSET_SENDER = 32;\n    uint256 private constant OFFSET_RECIPIENT = 64;\n    uint256 private constant OFFSET_REQUEST = OFFSET_RECIPIENT + TIPS_LENGTH;\n    uint256 private constant OFFSET_CONTENT = OFFSET_REQUEST + REQUEST_LENGTH;\n\n    // ═══════════════════════════════════════════════ BASE MESSAGE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted BaseMessage payload with provided fields.\n     * @param tips_         Encoded tips information\n     * @param sender_       Sender address on origin chain\n     * @param recipient_    Recipient address on destination chain\n     * @param request_      Encoded request for message execution\n     * @param content_      Raw content to be passed to recipient on destination chain\n     * @return Formatted base message\n     */\n    function formatBaseMessage(Tips tips_, bytes32 sender_, bytes32 recipient_, Request request_, bytes memory content_)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return abi.encodePacked(tips_, sender_, recipient_, request_, content_);\n    }\n\n    /**\n     * @notice Returns a BaseMessage view over the given payload.\n     * @dev Will revert if the payload is not a base message.\n     */\n    function castToBaseMessage(bytes memory payload) internal pure returns (BaseMessage) {\n        return castToBaseMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a BaseMessage view.\n     * @dev Will revert if the memory view is not over a base message payload.\n     */\n    function castToBaseMessage(MemView memView) internal pure returns (BaseMessage) {\n        if (!isBaseMessage(memView)) revert UnformattedBaseMessage();\n        return BaseMessage.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted BaseMessage.\n    function isBaseMessage(MemView memView) internal pure returns (bool) {\n        // Check if sender, recipient, tips fields exist\n        return (memView.len() \u003e= OFFSET_CONTENT);\n        // Content could be empty, so we don't check that\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(BaseMessage baseMessage) internal pure returns (MemView) {\n        return MemView.wrap(BaseMessage.unwrap(baseMessage));\n    }\n\n    /// @notice Returns baseMessage's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        // We hash \"tips\" and \"everything but tips\" to make tips proofs easier to verify\n        return MerkleMath.getParent(baseMessage.tips().leaf(), baseMessage.bodyLeaf());\n    }\n\n    /// @notice Returns hash for the \"everything but tips\" part of the base message.\n    function bodyLeaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_SENDER}).keccak();\n    }\n\n    // ═══════════════════════════════════════════ BASE MESSAGE SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips paid on origin chain.\n    function tips(BaseMessage baseMessage) internal pure returns (Tips) {\n        return TipsLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_TIPS, bytes_: TIPS_LENGTH})));\n    }\n\n    /// @notice Returns sender address on origin chain.\n    function sender(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_SENDER, bytes_: 32});\n    }\n\n    /// @notice Returns recipient address on destination chain.\n    function recipient(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_RECIPIENT, bytes_: 32});\n    }\n\n    /// @notice Returns an encoded request for message execution on destination chain.\n    function request(BaseMessage baseMessage) internal pure returns (Request) {\n        return RequestLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_REQUEST, bytes_: REQUEST_LENGTH})));\n    }\n\n    /// @notice Returns an untyped memory view over the content to be passed to recipient.\n    function content(BaseMessage baseMessage) internal pure returns (MemView) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_CONTENT});\n    }\n}\n\n// contracts/base/MessagingBase.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for all messaging contracts.\n * - Provides context on the local chain's domain.\n * - Provides ownership functionality.\n * - Will be providing pausing functionality when it is implemented.\n */\nabstract contract MessagingBase is MultiCallable, Versioned, Ownable2StepUpgradeable {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @notice Domain of the local chain, set once upon contract creation\n    uint32 public immutable localDomain;\n    // @notice Domain of the Synapse chain, set once upon contract creation\n    uint32 public immutable synapseDomain;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev gap for upgrade safety\n    uint256[50] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    constructor(string memory version_, uint32 synapseDomain_) Versioned(version_) {\n        localDomain = ChainContext.chainId();\n        synapseDomain = synapseDomain_;\n    }\n\n    // TODO: Implement pausing\n\n    /**\n     * @dev Should be impossible to renounce ownership;\n     * we override OpenZeppelin OwnableUpgradeable's\n     * implementation of renounceOwnership to make it a no-op\n     */\n    function renounceOwnership() public override onlyOwner {} //solhint-disable-line no-empty-blocks\n}\n\n// contracts/libs/memory/Message.sol\n\n/// Message is a memory over over a formatted message payload.\ntype Message is uint256;\n\nusing MessageLib for Message global;\n\n/// Library for formatting the various messages supported by Origin and Destination.\n///\n/// # Message memory layout\n///\n/// | Position   | Field  | Type    | Bytes | Description                                             |\n/// | ---------- | ------ | ------- | ----- | ------------------------------------------------------- |\n/// | [000..017) | header | uint136 | 17    | Encoded general routing information for the message     |\n/// | [017..AAA) | body   | bytes   | ??    | Formatted payload (according to flag) with message body |\nlibrary MessageLib {\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MemViewLib for bytes;\n    using HeaderLib for MemView;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_HEADER = 0;\n    uint256 private constant OFFSET_BODY = OFFSET_HEADER + HEADER_LENGTH;\n\n    // ══════════════════════════════════════════════════ MESSAGE ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns formatted message with provided fields.\n     * @param header_   Encoded general routing information for the message\n     * @param body_     Formatted payload (according to flag) with message body\n     * @return Formatted message\n     */\n    function formatMessage(Header header_, bytes memory body_) internal pure returns (bytes memory) {\n        return abi.encodePacked(header_, body_);\n    }\n\n    /**\n     * @notice Returns a Message view over for the given payload.\n     * @dev Will revert if the payload is not a message payload.\n     */\n    function castToMessage(bytes memory payload) internal pure returns (Message) {\n        return castToMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Message view.\n     * @dev Will revert if the memory view is not over a message payload.\n     */\n    function castToMessage(MemView memView) internal pure returns (Message) {\n        if (!isMessage(memView)) revert UnformattedMessage();\n        return Message.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Message.\n     */\n    function isMessage(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Check if headers exist in the payload\n        if (length \u003c OFFSET_BODY) return false;\n        // Check that Header is valid\n        uint256 paddedHeader = _header(memView);\n        if (!HeaderLib.isHeader(paddedHeader)) return false;\n        // Check that body is formatted according to the flag\n        // Only Base/Manager message flags exist\n        if (HeaderLib.wrapPadded(paddedHeader).flag() == MessageFlag.Base) {\n            // Check if body is a formatted base message\n            return _body(memView).isBaseMessage();\n        } else {\n            // Check if body is a formatted calldata for AgentManager call\n            return _body(memView).isCallData();\n        }\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Message message) internal pure returns (MemView) {\n        return MemView.wrap(Message.unwrap(message));\n    }\n\n    /// @notice Returns message's hash: a leaf to be inserted in the Merkle tree.\n    function leaf(Message message) internal pure returns (bytes32) {\n        // We hash header and body separately to make message proofs easier to verify\n        Header header_ = message.header();\n        // Only Base/Manager message flags exist\n        if (header_.flag() == MessageFlag.Base) {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToBaseMessage().leaf());\n        } else {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToCallData().leaf());\n        }\n    }\n\n    // ══════════════════════════════════════════════ MESSAGE SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns message's encoded header field.\n    function header(Message message) internal pure returns (Header) {\n        return HeaderLib.wrapPadded((message.unwrap().indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH})));\n    }\n\n    /// @notice Returns message's body field as an untyped memory view.\n    function body(Message message) internal pure returns (MemView) {\n        MemView memView = message.unwrap();\n        return _body(memView);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns message's padded header without checking that it is a valid header.\n    function _header(MemView memView) private pure returns (uint256) {\n        return memView.indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH});\n    }\n\n    /// @dev Returns an untyped memory view over the body field without checking\n    /// if the whole payload or the body are properly formatted.\n    function _body(MemView memView) private pure returns (MemView) {\n        return memView.sliceFrom({index_: OFFSET_BODY});\n    }\n}\n\n// contracts/base/AgentSecured.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for messaging contracts that are secured by the agent manager.\n * `AgentSecured` relies on `AgentManager` to provide the following functionality:\n * - Keep track of agents and their statuses.\n * - Pass agent-signed statements that were verified by the agent manager.\n * - These statements are considered valid indefinitely, unless the agent is disputed.\n * - Disputes are opened and resolved by the agent manager.\n * \u003e `AgentSecured` implementation should never use statements signed by agents that are disputed.\n */\nabstract contract AgentSecured is MessagingBase, IAgentSecured {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    address public immutable agentManager;\n\n    /// @inheritdoc IAgentSecured\n    address public immutable inbox;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    // (agent index =\u003e their dispute status: flag, openedAt, resolvedAt)\n    mapping(uint32 =\u003e DisputeStatus) internal _disputes;\n\n    /// @dev gap for upgrade safety\n    uint256[49] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    modifier onlyAgentManager() {\n        if (msg.sender != agentManager) revert CallerNotAgentManager();\n        _;\n    }\n\n    modifier onlyInbox() {\n        if (msg.sender != inbox) revert CallerNotInbox();\n        _;\n    }\n\n    constructor(string memory version_, uint32 synapseDomain_, address agentManager_, address inbox_)\n        MessagingBase(version_, synapseDomain_)\n    {\n        agentManager = agentManager_;\n        inbox = inbox_;\n    }\n\n    // ════════════════════════════════════════════ ONLY AGENT MANAGER ═════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external onlyAgentManager {\n        uint40 openedAt = ChainContext.blockTimestamp();\n        DisputeStatus memory status = DisputeStatus({flag: DisputeFlag.Pending, openedAt: openedAt, resolvedAt: 0});\n        _disputes[guardIndex] = status;\n        _disputes[notaryIndex] = status;\n    }\n\n    /// @inheritdoc IAgentSecured\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external onlyAgentManager {\n        // Update the dispute status of the slashed agent first.\n        uint40 resolvedAt = ChainContext.blockTimestamp();\n        _disputes[slashedIndex].flag = DisputeFlag.Slashed;\n        _disputes[slashedIndex].resolvedAt = resolvedAt;\n        // Mark the rival agent as not disputed, if there was an ongoing dispute.\n        if (rivalIndex != 0) {\n            _disputes[rivalIndex].flag = DisputeFlag.None;\n            _disputes[rivalIndex].resolvedAt = resolvedAt;\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function agentStatus(address agent) external view returns (AgentStatus memory) {\n        return _agentStatus(agent);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status) {\n        return _getAgent(index);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory) {\n        return _disputes[agentIndex];\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns status of the given agent: (flag, domain, index).\n    function _agentStatus(address agent) internal view returns (AgentStatus memory) {\n        return IAgentManager(agentManager).agentStatus(agent);\n    }\n\n    /// @dev Returns agent and their status for a given agent index. Returns zero values for non existing indexes.\n    function _getAgent(uint256 index) internal view returns (address agent, AgentStatus memory status) {\n        return IAgentManager(agentManager).getAgent(index);\n    }\n\n    /// @dev Checks if a Dispute exists for the given Notary. This function returns true, if\n    /// Notary is in ongoing Dispute, or if Dispute was resolved not in Notary's favor.\n    /// In both cases we can't trust Notary's data.\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeExists(uint32 notaryIndex) internal view returns (bool) {\n        return _disputes[notaryIndex].flag != DisputeFlag.None;\n    }\n\n    /// @dev Checks if a Notary recently won a Dispute and is still in the \"post-dispute\" timeout period.\n    /// In this period we still can't trust Notary's data, though we can optimistically assume that\n    /// that the data will be correct after the timeout (assuming no new Disputes are opened).\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeTimeout(uint32 notaryIndex) internal view returns (bool) {\n        DisputeStatus memory status = _disputes[notaryIndex];\n        // Exit early if Notary is in ongoing Dispute / slashed.\n        if (status.flag != DisputeFlag.None) return false;\n        // Check if Notary has been in any Dispute at all.\n        if (status.openedAt == 0) return false;\n        // Otherwise check if the Dispute timeout is still active.\n        return block.timestamp \u003c status.resolvedAt + DISPUTE_TIMEOUT_NOTARY;\n    }\n}\n\n// contracts/hubs/StateHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StateHub` is a parent contract for `Origin`. It is responsible for the following:\n/// - Keeping track of the historical Origin Merkle Tree containing all the message hashes.\n/// - Keeping track of the historical Origin States, as well as verifying their validity.\nabstract contract StateHub is AgentSecured, StateHubEvents, IStateHub {\n    using SafeCast for uint256;\n    using StateLib for bytes;\n\n    struct OriginState {\n        uint40 blockNumber;\n        uint40 timestamp;\n        GasData gasData;\n    }\n    // Bits left for tight packing: 80\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Historical Merkle Tree\n    /// Note: Takes two storage slots\n    HistoricalTree private _tree;\n\n    /// @dev All historical contract States\n    OriginState[] private _originStates;\n\n    /// @dev gap for upgrade safety\n    uint256[47] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IStateHub\n    function isValidState(bytes memory statePayload) external view returns (bool isValid) {\n        // This will revert if payload is not a formatted state\n        State state = statePayload.castToState();\n        return _isValidState(state);\n    }\n\n    /// @inheritdoc IStateHub\n    function statesAmount() external view returns (uint256) {\n        return _originStates.length;\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestLatestState() external view returns (bytes memory stateData) {\n        // This never underflows, assuming the contract was initialized\n        return suggestState(_nextNonce() - 1);\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestState(uint32 nonce) public view returns (bytes memory stateData) {\n        // This will revert if nonce is out of range\n        bytes32 root = _tree.root(nonce);\n        return _formatOriginState(_originStates[nonce], root, localDomain, nonce);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Initializes the saved states list by inserting a state for an empty Merkle Tree.\n    function _initializeStates() internal {\n        // This should only be called once, when the contract is initialized\n        // This will revert if _tree.roots is non-empty\n        bytes32 savedRoot = _tree.initializeRoots();\n        // Save root for empty merkle _tree with block number and timestamp of initialization\n        _saveState(savedRoot, _toOriginState());\n    }\n\n    /// @dev Inserts leaf into the Merkle Tree and saves the updated origin State.\n    function _insertAndSave(bytes32 leaf) internal {\n        bytes32 newRoot = _tree.insert(leaf);\n        _saveState(newRoot, _toOriginState());\n    }\n\n    /// @dev Saves an updated state of the Origin contract\n    function _saveState(bytes32 root, OriginState memory state) internal {\n        uint32 nonce = _nextNonce();\n        _originStates.push(state);\n        // Emit event with raw state data\n        emit StateSaved(_formatOriginState(state, root, localDomain, nonce));\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns nonce of the next sent message: the amount of saved States so far.\n    /// This always equals to \"total amount of sent messages\" plus 1.\n    function _nextNonce() internal view returns (uint32) {\n        // TODO: consider using more than 32 bits for origin nonces\n        return _originStates.length.toUint32();\n    }\n\n    /// @dev Checks if a state is valid, i.e. if it matches the historical one.\n    /// Reverts, if state refers to another Origin contract.\n    function _isValidState(State state) internal view returns (bool) {\n        // Check if state refers to this contract\n        if (state.origin() != localDomain) revert IncorrectOriginDomain();\n        // Check if nonce exists\n        uint32 nonce = state.nonce();\n        if (nonce \u003e= _originStates.length) return false;\n        // Check if state root matches the historical one\n        if (state.root() != _tree.root(nonce)) return false;\n        // Check if state metadata matches the historical one\n        return _areEqual(state, _originStates[nonce]);\n    }\n\n    // ═════════════════════════════════════════════ STRUCT FORMATTING ═════════════════════════════════════════════════\n\n    /// @dev Returns a formatted payload for a stored OriginState.\n    function _formatOriginState(OriginState memory originState, bytes32 root, uint32 origin, uint32 nonce)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return StateLib.formatState({\n            root_: root,\n            origin_: origin,\n            nonce_: nonce,\n            blockNumber_: originState.blockNumber,\n            timestamp_: originState.timestamp,\n            gasData_: originState.gasData\n        });\n    }\n\n    /// @dev Child contract should implement the logic for getting the current gas data from the gas oracle\n    /// to be saved as part of the Origin State.\n    // solhint-disable-next-line ordering\n    function _fetchGasData() internal view virtual returns (GasData);\n\n    /// @dev Returns a OriginState struct to save in the contract.\n    function _toOriginState() internal view returns (OriginState memory originState) {\n        originState.blockNumber = ChainContext.blockNumber();\n        originState.timestamp = ChainContext.blockTimestamp();\n        originState.gasData = _fetchGasData();\n    }\n\n    /// @dev Checks that a state and its Origin representation are equal.\n    function _areEqual(State state, OriginState memory originState) internal pure returns (bool) {\n        return state.blockNumber() == originState.blockNumber \u0026\u0026 state.timestamp() == originState.timestamp;\n    }\n}\n\n// contracts/Origin.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Origin` contract is used for sending messages to remote chains. It is done\n/// by inserting the message hashes into the Origin Merkle, which makes it possible to\n/// prove that message was sent using the Merkle proof against the Origin Merkle Root. This essentially\n/// compresses the list of messages into a single 32-byte value that needs to be stored on the destination chain.\n/// `Origin` is responsible for the following:\n/// - Formatting the sent message payloads, and inserting their hashes into the Origin Merkle Tree.\n/// - Keeping track of its own historical states (see parent contract `StateHub`).\n/// - Enforcing minimum tip values for sent base messages based on the provided execution requests.\n/// - Distributing the collected tips upon request from a local `AgentManager` contract.\ncontract Origin is StateHub, OriginEvents, InterfaceOrigin {\n    using MemViewLib for bytes;\n    using MessageLib for bytes;\n    using TipsLib for bytes;\n    using TypeCasts for address;\n\n    address public immutable gasOracle;\n\n    modifier onlyRemoteDestination(uint32 destination) {\n        if (destination == localDomain) revert IncorrectDestinationDomain();\n        _;\n    }\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_, address gasOracle_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {\n        gasOracle = gasOracle_;\n    }\n\n    /// @notice Initializes Origin contract:\n    /// - msg.sender is set as contract owner\n    /// - State of \"empty merkle tree\" is saved\n    function initialize() external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize \"states\": state of an \"empty merkle tree\" is saved\n        _initializeStates();\n    }\n\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable onlyRemoteDestination(destination) returns (uint32 messageNonce, bytes32 messageHash) {\n        // Check that content is not too large\n        if (content.length \u003e MAX_CONTENT_BYTES) revert ContentLengthTooBig();\n        // This will revert if msg.value is lower than value of minimum tips\n        Tips tips = _getMinimumTips(destination, paddedRequest, content.length).matchValue(msg.value);\n        Request request = RequestLib.wrapPadded(paddedRequest);\n        // Format the BaseMessage body\n        bytes memory body = BaseMessageLib.formatBaseMessage({\n            sender_: msg.sender.addressToBytes32(),\n            recipient_: recipient,\n            tips_: tips,\n            request_: request,\n            content_: content\n        });\n        // Send the message\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Base, body);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        onlyAgentManager\n        onlyRemoteDestination(destination)\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // AgentManager (checked via modifier) is responsible for constructing the calldata payload correctly.\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Manager, payload);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function withdrawTips(address recipient, uint256 amount) external onlyAgentManager {\n        if (address(this).balance \u003c amount) revert InsufficientEthBalance();\n        (bool success,) = recipient.call{value: amount}(\"\");\n        if (!success) revert EthTransferFailed();\n        emit TipWithdrawalCompleted(recipient, amount);\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue)\n    {\n        return _getMinimumTips(destination, paddedRequest, contentLength).value();\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Sends the given message to the specified destination. Message hash is inserted\n    /// into the Origin Merkle Tree, which will enable message execution on destination chain.\n    function _sendMessage(uint32 destination, uint32 optimisticPeriod, MessageFlag flag, bytes memory body)\n        internal\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // Format the message header\n        messageNonce = _nextNonce();\n        Header header = flag.encodeHeader({\n            origin_: localDomain,\n            nonce_: messageNonce,\n            destination_: destination,\n            optimisticPeriod_: optimisticPeriod\n        });\n        // Format the full message payload\n        bytes memory msgPayload = MessageLib.formatMessage(header, body);\n        // Insert new leaf into the Origin Merkle Tree and save the updated state\n        messageHash = msgPayload.castToMessage().leaf();\n        _insertAndSave(messageHash);\n        // Emit event with message information\n        emit Sent(messageHash, messageNonce, destination, msgPayload);\n        // Update the gas oracle data. We do this after the provided tips are checked so that\n        // the provided message is sent in the event that the gas oracle data is updated to a higher value.\n        InterfaceGasOracle(gasOracle).updateGasData(destination);\n        // TODO: consider doing this before the message is sent, while adjusting GasOracle.getMinimumTips() to\n        // use the pending gas oracle data.\n    }\n\n    /// @dev Returns the minimum tips for sending a message to the given destination with the given request and content.\n    function _getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        internal\n        view\n        returns (Tips)\n    {\n        return\n            TipsLib.wrapPadded(InterfaceGasOracle(gasOracle).getMinimumTips(destination, paddedRequest, contentLength));\n    }\n\n    /// @dev Gets the current gas data from the gas oracle to be saved as part of the Origin State.\n    function _fetchGasData() internal view override returns (GasData) {\n        return GasDataLib.wrapGasData(InterfaceGasOracle(gasOracle).getGasData());\n    }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"25686:2478:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;25686:2478:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"25686:2478:0:-:0;;;;;;;;","abiDefinition":[],"userDoc":{"kind":"user","methods":{},"notice":"Library for formatting _the request part_ of _the base messages_. - Request represents a message sender requirements for the message execution on the destination chain. - Request occupies a single storage word, and thus is stored on stack instead of being stored in memory. \u003e gasDrop field is included for future compatibility and is ignored at the moment. # Request stack layout (from highest bits to lowest) | Position   | Field    | Type   | Bytes | Description                                          | | ---------- | -------- | ------ | ----- | ---------------------------------------------------- | | (024..012] | gasDrop  | uint96 | 12    | Minimum amount of gas token to drop to the recipient | | (012..004] | gasLimit | uint64 | 8     | Minimum amount of gas units to supply for execution  | | (004..000] | version  | uint32 | 4     | Base message version to pass to the recipient        |","version":1},"developerDoc":{"kind":"dev","methods":{},"stateVariables":{"SHIFT_GAS_DROP":{"details":"Amount of bits to shift to gasDrop field"},"SHIFT_GAS_LIMIT":{"details":"Amount of bits to shift to gasLimit field"}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"stateVariables\":{\"SHIFT_GAS_DROP\":{\"details\":\"Amount of bits to shift to gasDrop field\"},\"SHIFT_GAS_LIMIT\":{\"details\":\"Amount of bits to shift to gasLimit field\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"Library for formatting _the request part_ of _the base messages_. - Request represents a message sender requirements for the message execution on the destination chain. - Request occupies a single storage word, and thus is stored on stack instead of being stored in memory. \u003e gasDrop field is included for future compatibility and is ignored at the moment. # Request stack layout (from highest bits to lowest) | Position   | Field    | Type   | Bytes | Description                                          | | ---------- | -------- | ------ | ----- | ---------------------------------------------------- | | (024..012] | gasDrop  | uint96 | 12    | Minimum amount of gas token to drop to the recipient | | (012..004] | gasLimit | uint64 | 8     | Minimum amount of gas units to supply for execution  | | (004..000] | version  | uint32 | 4     | Base message version to pass to the recipient        |\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Origin.sol\":\"RequestLib\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Origin.sol\":{\"keccak256\":\"0x96775924f147f3d1f8df8cdf56731fe52a15af8d8e12e608efb8158c112b18cd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e642a27f5fab3c62b4c02e9754e9e42b1cf2e5381dbea9d3d106d23b7772ebe6\",\"dweb:/ipfs/QmUwn7ZyBvPkjnMuK8ZMSexBUdNQnVtxwyoAyT4DXLQjra\"]}},\"version\":1}"},"hashes":{}},"solidity/Origin.sol:SafeCast":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220db1a900b70d0dca7be2753a46dd0ed7b773e188e76ed743f2a75fd3f235d88fc64736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220db1a900b70d0dca7be2753a46dd0ed7b773e188e76ed743f2a75fd3f235d88fc64736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/OriginEvents.sol\n\n/// @notice A collection of events emitted by the Origin contract\nabstract contract OriginEvents {\n    /**\n     * @notice Emitted when a new message is sent.\n     * @param messageHash   Hash of message; the leaf inserted to the Merkle tree for the message\n     * @param nonce         Nonce of sent message (starts from 1)\n     * @param destination   Destination domain\n     * @param message       Raw bytes of message\n     */\n    event Sent(bytes32 indexed messageHash, uint32 indexed nonce, uint32 indexed destination, bytes message);\n\n    /**\n     * @notice Emitted when a tip withdrawal is completed.\n     * @param actor     Actor address\n     * @param tip       Tip value, denominated in local domain's wei\n     */\n    event TipWithdrawalCompleted(address actor, uint256 tip);\n}\n\n// contracts/events/StateHubEvents.sol\n\n/// @notice A collection of events emitted by the StateHub contract\nabstract contract StateHubEvents {\n    /**\n     * @notice Emitted when a new Origin State is saved after a message was sent.\n     * @param state     Raw payload with state data\n     */\n    event StateSaved(bytes state);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n    /**\n     * @notice Check that a given state is valid: matches the historical state of Origin contract.\n     * Note: any Agent including an invalid state in their snapshot will be slashed\n     * upon providing the snapshot and agent signature for it to Origin contract.\n     * @dev Will revert if any of these is true:\n     *  - State payload is not properly formatted.\n     * @param statePayload      Raw payload with state data\n     * @return isValid          Whether the provided state is valid\n     */\n    function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns the amount of saved states so far.\n     * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n     */\n    function statesAmount() external view returns (uint256);\n\n    /**\n     * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @return statePayload     Raw payload with the latest state data\n     */\n    function suggestLatestState() external view returns (bytes memory statePayload);\n\n    /**\n     * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @param nonce             Historical nonce to form a state\n     * @return statePayload     Raw payload with historical state data\n     */\n    function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/InterfaceGasOracle.sol\n\ninterface InterfaceGasOracle {\n    /**\n     * @notice Fetches the latest gas data for the chain from `Destination` contract,\n     * and uses it to update the oracle values for the requested chain.\n     * @param domain    Domain to update the gas data for\n     */\n    function updateGasData(uint32 domain) external;\n\n    /**\n     * @notice Returns the gas data for the local chain.\n     */\n    function getGasData() external view returns (uint256 paddedGasData);\n\n    /**\n     * @notice Returns the gas data for the given domain, in the decoded format.\n     * @param domain        Domain of chain to get gas data for\n     * @return gasPrice     Gas price for the chain (in Wei per gas unit)\n     * @return dataPrice    Calldata price (in Wei per byte of content)\n     * @return execBuffer   Tx fee safety buffer for message execution (in Wei)\n     * @return amortAttCost Amortized cost for attestation submission (in Wei)\n     * @return etherPrice   Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n     * @return markup       Markup for the message execution (in BWAD)\n     */\n    function getDecodedGasData(uint32 domain)\n        external\n        view\n        returns (\n            uint256 gasPrice,\n            uint256 dataPrice,\n            uint256 execBuffer,\n            uint256 amortAttCost,\n            uint256 etherPrice,\n            uint256 markup\n        );\n\n    /**\n     * @notice Returns the minimum tips for sending a message to a given destination.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return paddedTips       Padded encoded minimum tips information\n     */\n    function getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 paddedTips);\n}\n\n// contracts/interfaces/InterfaceOrigin.sol\n\ninterface InterfaceOrigin {\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /**\n     * @notice Send a message to the recipient located on destination domain.\n     * @dev Recipient has to conform to IMessageRecipient interface, otherwise message won't be delivered.\n     * Will revert if any of these is true:\n     * - `destination` is equal to contract's local domain\n     * - `content` length is greater than `MAX_CONTENT_BYTES`\n     * - `msg.value` is lower than value of minimum tips for the given message\n     * @param destination           Domain of destination chain\n     * @param recipient             Address of recipient on destination chain as bytes32\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param paddedRequest         Padded encoded message execution request on destination chain\n     * @param content               Raw bytes content of message\n     * @return messageNonce         Nonce of the sent message\n     * @return messageHash          Hash of the sent message\n     */\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable returns (uint32 messageNonce, bytes32 messageHash);\n\n    /**\n     * @notice Send a manager message to the destination domain.\n     * @dev This could only be called by AgentManager, which takes care of encoding the calldata payload.\n     * Note: (msgOrigin, proofMaturity) security args will be added to payload on the destination chain\n     * so that the AgentManager could verify where the Manager Message came from and how mature is the proof.\n     * Note: function is not payable, as no tips are required for sending a manager message.\n     * Will revert if `destination` is equal to contract's local domain.\n     * @param destination           Domain of destination chain\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param payload               Payload for calling AgentManager on destination chain (with extra security args)\n     */\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        returns (uint32 messageNonce, bytes32 messageHash);\n\n    // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Withdraws locked base message tips to the recipient.\n     * @dev Could only be called by a local AgentManager.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function withdrawTips(address recipient, uint256 amount) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the minimum tips value for sending a message to a given destination.\n     * @dev Using at least `tipsValue` as `msg.value` for `sendBaseMessage()`\n     * will guarantee that the message will be accepted.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return tipsValue        Minimum tips value for a message to be accepted\n     */\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue);\n}\n\n// contracts/libs/Constants.sol\n\n// Here we define common constants to enable their easier reusing later.\n\n// ══════════════════════════════════ MERKLE ═══════════════════════════════════\n/// @dev Height of the Agent Merkle Tree\nuint256 constant AGENT_TREE_HEIGHT = 32;\n/// @dev Height of the Origin Merkle Tree\nuint256 constant ORIGIN_TREE_HEIGHT = 32;\n/// @dev Height of the Snapshot Merkle Tree. Allows up to 64 leafs, e.g. up to 32 states\nuint256 constant SNAPSHOT_TREE_HEIGHT = 6;\n// ══════════════════════════════════ STRUCTS ══════════════════════════════════\n/// @dev See Attestation.sol: (bytes32,bytes32,uint32,uint40,uint40): 32+32+4+5+5\nuint256 constant ATTESTATION_LENGTH = 78;\n/// @dev See GasData.sol: (uint16,uint16,uint16,uint16,uint16,uint16): 2+2+2+2+2+2\nuint256 constant GAS_DATA_LENGTH = 12;\n/// @dev See Receipt.sol: (uint32,uint32,bytes32,bytes32,uint8,address,address,address): 4+4+32+32+1+20+20+20\nuint256 constant RECEIPT_LENGTH = 133;\n/// @dev See State.sol: (bytes32,uint32,uint32,uint40,uint40,GasData): 32+4+4+5+5+len(GasData)\nuint256 constant STATE_LENGTH = 50 + GAS_DATA_LENGTH;\n/// @dev Maximum amount of states in a single snapshot. Each state produces two leafs in the tree\nuint256 constant SNAPSHOT_MAX_STATES = 1 \u003c\u003c (SNAPSHOT_TREE_HEIGHT - 1);\n// ══════════════════════════════════ MESSAGE ══════════════════════════════════\n/// @dev See Header.sol: (uint8,uint32,uint32,uint32,uint32): 1+4+4+4+4\nuint256 constant HEADER_LENGTH = 17;\n/// @dev See Request.sol: (uint96,uint64,uint32): 12+8+4\nuint256 constant REQUEST_LENGTH = 24;\n/// @dev See Tips.sol: (uint64,uint64,uint64,uint64): 8+8+8+8\nuint256 constant TIPS_LENGTH = 32;\n/// @dev The amount of discarded last bits when encoding tip values\nuint256 constant TIPS_GRANULARITY = 32;\n/// @dev Tip values could be only the multiples of TIPS_MULTIPLIER\nuint256 constant TIPS_MULTIPLIER = 1 \u003c\u003c TIPS_GRANULARITY;\n// ══════════════════════════════ STATEMENT SALTS ══════════════════════════════\n/// @dev Salts for signing various statements\nbytes32 constant ATTESTATION_VALID_SALT = keccak256(\"ATTESTATION_VALID_SALT\");\nbytes32 constant ATTESTATION_INVALID_SALT = keccak256(\"ATTESTATION_INVALID_SALT\");\nbytes32 constant RECEIPT_VALID_SALT = keccak256(\"RECEIPT_VALID_SALT\");\nbytes32 constant RECEIPT_INVALID_SALT = keccak256(\"RECEIPT_INVALID_SALT\");\nbytes32 constant SNAPSHOT_VALID_SALT = keccak256(\"SNAPSHOT_VALID_SALT\");\nbytes32 constant STATE_INVALID_SALT = keccak256(\"STATE_INVALID_SALT\");\n// ═════════════════════════════════ PROTOCOL ══════════════════════════════════\n/// @dev Optimistic period for new agent roots in LightManager\nuint32 constant AGENT_ROOT_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Timeout between the agent root could be proposed and resolved in LightManager\nuint32 constant AGENT_ROOT_PROPOSAL_TIMEOUT = 12 hours;\nuint32 constant BONDING_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Amount of time that the Notary will not be considered active after they won a dispute\nuint32 constant DISPUTE_TIMEOUT_NOTARY = 12 hours;\n/// @dev Amount of time without fresh data from Notaries before contract owner can resolve stuck disputes manually\nuint256 constant FRESH_DATA_TIMEOUT = 4 hours;\n/// @dev Maximum bytes per message = 2 KiB (somewhat arbitrarily set to begin)\nuint256 constant MAX_CONTENT_BYTES = 2 * 2 ** 10;\n/// @dev Maximum value for the summit tip that could be set in GasOracle\nuint256 constant MAX_SUMMIT_TIP = 0.01 ether;\n\n// contracts/libs/Errors.sol\n\n// ══════════════════════════════ INVALID CALLER ═══════════════════════════════\n\nerror CallerNotAgentManager();\nerror CallerNotDestination();\nerror CallerNotInbox();\nerror CallerNotSummit();\n\n// ══════════════════════════════ INCORRECT DATA ═══════════════════════════════\n\nerror IncorrectAttestation();\nerror IncorrectAgentDomain();\nerror IncorrectAgentIndex();\nerror IncorrectAgentProof();\nerror IncorrectAgentRoot();\nerror IncorrectDataHash();\nerror IncorrectDestinationDomain();\nerror IncorrectOriginDomain();\nerror IncorrectSnapshotProof();\nerror IncorrectSnapshotRoot();\nerror IncorrectState();\nerror IncorrectStatesAmount();\nerror IncorrectTipsProof();\nerror IncorrectVersionLength();\n\nerror IncorrectNonce();\nerror IncorrectSender();\nerror IncorrectRecipient();\n\nerror FlagOutOfRange();\nerror IndexOutOfRange();\nerror NonceOutOfRange();\n\nerror OutdatedNonce();\n\nerror UnformattedAttestation();\nerror UnformattedAttestationReport();\nerror UnformattedBaseMessage();\nerror UnformattedCallData();\nerror UnformattedCallDataPrefix();\nerror UnformattedMessage();\nerror UnformattedReceipt();\nerror UnformattedReceiptReport();\nerror UnformattedSignature();\nerror UnformattedSnapshot();\nerror UnformattedState();\nerror UnformattedStateReport();\n\n// ═══════════════════════════════ MERKLE TREES ════════════════════════════════\n\nerror LeafNotProven();\nerror MerkleTreeFull();\nerror NotEnoughLeafs();\nerror TreeHeightTooLow();\n\n// ═════════════════════════════ OPTIMISTIC PERIOD ═════════════════════════════\n\nerror BaseClientOptimisticPeriod();\nerror MessageOptimisticPeriod();\nerror SlashAgentOptimisticPeriod();\nerror WithdrawTipsOptimisticPeriod();\nerror ZeroProofMaturity();\n\n// ═══════════════════════════════ AGENT MANAGER ═══════════════════════════════\n\nerror AgentNotGuard();\nerror AgentNotNotary();\n\nerror AgentCantBeAdded();\nerror AgentNotActive();\nerror AgentNotActiveNorUnstaking();\nerror AgentNotFraudulent();\nerror AgentNotUnstaking();\nerror AgentUnknown();\n\nerror AgentRootNotProposed();\nerror AgentRootTimeoutNotOver();\n\nerror NotStuck();\n\nerror DisputeAlreadyResolved();\nerror DisputeNotOpened();\nerror DisputeTimeoutNotOver();\nerror GuardInDispute();\nerror NotaryInDispute();\n\nerror MustBeSynapseDomain();\nerror SynapseDomainForbidden();\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\nerror AlreadyExecuted();\nerror AlreadyFailed();\nerror DuplicatedSnapshotRoot();\nerror IncorrectMagicValue();\nerror GasLimitTooLow();\nerror GasSuppliedTooLow();\n\n// ══════════════════════════════════ ORIGIN ═══════════════════════════════════\n\nerror ContentLengthTooBig();\nerror EthTransferFailed();\nerror InsufficientEthBalance();\n\n// ════════════════════════════════ GAS ORACLE ═════════════════════════════════\n\nerror LocalGasDataNotSet();\nerror RemoteGasDataNotSet();\n\n// ═══════════════════════════════════ TIPS ════════════════════════════════════\n\nerror SummitTipTooHigh();\nerror TipsClaimMoreThanEarned();\nerror TipsClaimZero();\nerror TipsOverflow();\nerror TipsValueTooLow();\n\n// ════════════════════════════════ MEMORY VIEW ════════════════════════════════\n\nerror IndexedTooMuch();\nerror ViewOverrun();\nerror OccupiedMemory();\nerror UnallocatedMemory();\nerror PrecompileOutOfGas();\n\n// ═════════════════════════════════ MULTICALL ═════════════════════════════════\n\nerror MulticallFailed();\n\n// contracts/libs/TypeCasts.sol\n\nlibrary TypeCasts {\n    // alignment preserving cast\n    function addressToBytes32(address addr) internal pure returns (bytes32) {\n        return bytes32(uint256(uint160(addr)));\n    }\n\n    // alignment preserving cast\n    function bytes32ToAddress(bytes32 buf) internal pure returns (address) {\n        return address(uint160(uint256(buf)));\n    }\n}\n\n// contracts/libs/stack/Number.sol\n\n/// Number is a compact representation of uint256, that is fit into 16 bits\n/// with the maximum relative error under 0.4%.\ntype Number is uint16;\n\nusing NumberLib for Number global;\n\n/// # Number\n/// Library for compact representation of uint256 numbers.\n/// - Number is stored using mantissa and exponent, each occupying 8 bits.\n/// - Numbers under 2**8 are stored as `mantissa` with `exponent = 0xFF`.\n/// - Numbers at least 2**8 are approximated as `(256 + mantissa) \u003c\u003c exponent`\n/// \u003e - `0 \u003c= mantissa \u003c 256`\n/// \u003e - `0 \u003c= exponent \u003c= 247` (`256 * 2**248` doesn't fit into uint256)\n/// # Number stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type  | Bytes |\n/// | ---------- | -------- | ----- | ----- |\n/// | (002..001] | mantissa | uint8 | 1     |\n/// | (001..000] | exponent | uint8 | 1     |\n\nlibrary NumberLib {\n    /// @dev Amount of bits to shift to mantissa field\n    uint16 private constant SHIFT_MANTISSA = 8;\n\n    /// @notice For bwad math (binary wad) we use 2**64 as \"wad\" unit.\n    /// @dev We are using not using 10**18 as wad, because it is not stored precisely in NumberLib.\n    uint256 internal constant BWAD_SHIFT = 64;\n    uint256 internal constant BWAD = 1 \u003c\u003c BWAD_SHIFT;\n    /// @notice ~0.1% in bwad units.\n    uint256 internal constant PER_MILLE_SHIFT = BWAD_SHIFT - 10;\n    uint256 internal constant PER_MILLE = 1 \u003c\u003c PER_MILLE_SHIFT;\n\n    /// @notice Compresses uint256 number into 16 bits.\n    function compress(uint256 value) internal pure returns (Number) {\n        // Find `msb` such as `2**msb \u003c= value \u003c 2**(msb + 1)`\n        uint256 msb = mostSignificantBit(value);\n        // We want to preserve 9 bits of precision.\n        // The highest bit is always 1, so we can skip it.\n        // The remaining 8 highest bits are stored as mantissa.\n        if (msb \u003c 8) {\n            // Value is less than 2**8, so we can use value as mantissa with \"-1\" exponent.\n            return _encode(uint8(value), 0xFF);\n        } else {\n            // We use `msb - 8` as exponent otherwise. Note that `exponent \u003e= 0`.\n            unchecked {\n                uint256 exponent = msb - 8;\n                // Shifting right by `msb-8` bits will shift the \"remaining 8 highest bits\" into the 8 lowest bits.\n                // uint8() will truncate the highest bit.\n                return _encode(uint8(value \u003e\u003e exponent), uint8(exponent));\n            }\n        }\n    }\n\n    /// @notice Decompresses 16 bits number into uint256.\n    /// @dev The outcome is an approximation of the original number: `(value - value / 256) \u003c number \u003c= value`.\n    function decompress(Number number) internal pure returns (uint256 value) {\n        // Isolate 8 highest bits as the mantissa.\n        uint256 mantissa = Number.unwrap(number) \u003e\u003e SHIFT_MANTISSA;\n        // This will truncate the highest bits, leaving only the exponent.\n        uint256 exponent = uint8(Number.unwrap(number));\n        if (exponent == 0xFF) {\n            return mantissa;\n        } else {\n            unchecked {\n                return (256 + mantissa) \u003c\u003c (exponent);\n            }\n        }\n    }\n\n    /// @dev Returns the most significant bit of `x`\n    /// https://solidity-by-example.org/bitwise/\n    function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\n        // To find `msb` we determine it bit by bit, starting from the highest one.\n        // `0 \u003c= msb \u003c= 255`, so we start from the highest bit, 1\u003c\u003c7 == 128.\n        // If `x` is at least 2**128, then the highest bit of `x` is at least 128.\n        // solhint-disable no-inline-assembly\n        assembly {\n            // `f` is set to 1\u003c\u003c7 if `x \u003e= 2**128` and to 0 otherwise.\n            let f := shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\n            // If `x \u003e= 2**128` then set `msb` highest bit to 1 and shift `x` right by 128.\n            // Otherwise, `msb` remains 0 and `x` remains unchanged.\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        // `x` is now at most 2**128 - 1. Continue the same way, the next highest bit is 1\u003c\u003c6 == 64.\n        assembly {\n            // `f` is set to 1\u003c\u003c6 if `x \u003e= 2**64` and to 0 otherwise.\n            let f := shl(6, gt(x, 0xFFFFFFFFFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c5 if `x \u003e= 2**32` and to 0 otherwise.\n            let f := shl(5, gt(x, 0xFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c4 if `x \u003e= 2**16` and to 0 otherwise.\n            let f := shl(4, gt(x, 0xFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c3 if `x \u003e= 2**8` and to 0 otherwise.\n            let f := shl(3, gt(x, 0xFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c2 if `x \u003e= 2**4` and to 0 otherwise.\n            let f := shl(2, gt(x, 0xF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c1 if `x \u003e= 2**2` and to 0 otherwise.\n            let f := shl(1, gt(x, 0x3))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1 if `x \u003e= 2**1` and to 0 otherwise.\n            let f := gt(x, 0x1)\n            msb := or(msb, f)\n        }\n    }\n\n    /// @dev Wraps (mantissa, exponent) pair into Number.\n    function _encode(uint8 mantissa, uint8 exponent) private pure returns (Number) {\n        // Casts below are upcasts, so they are safe.\n        return Number.wrap(uint16(mantissa) \u003c\u003c SHIFT_MANTISSA | uint16(exponent));\n    }\n}\n\n// contracts/libs/stack/Request.sol\n\n/// Request is encoded data with \"message execution request\".\ntype Request is uint192;\n\nusing RequestLib for Request global;\n\n/// Library for formatting _the request part_ of _the base messages_.\n/// - Request represents a message sender requirements for the message execution on the destination chain.\n/// - Request occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n/// \u003e gasDrop field is included for future compatibility and is ignored at the moment.\n///\n/// # Request stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type   | Bytes | Description                                          |\n/// | ---------- | -------- | ------ | ----- | ---------------------------------------------------- |\n/// | (024..012] | gasDrop  | uint96 | 12    | Minimum amount of gas token to drop to the recipient |\n/// | (012..004] | gasLimit | uint64 | 8     | Minimum amount of gas units to supply for execution  |\n/// | (004..000] | version  | uint32 | 4     | Base message version to pass to the recipient        |\n\nlibrary RequestLib {\n    /// @dev Amount of bits to shift to gasDrop field\n    uint192 private constant SHIFT_GAS_DROP = 12 * 8;\n    /// @dev Amount of bits to shift to gasLimit field\n    uint192 private constant SHIFT_GAS_LIMIT = 4 * 8;\n\n    /// @notice Returns an encoded request with the given fields\n    /// @param gasDrop_     Minimum amount of gas token to drop to the recipient (ignored at the moment)\n    /// @param gasLimit_    Minimum amount of gas units to supply for execution\n    /// @param version_     Base message version to pass to the recipient\n    function encodeRequest(uint96 gasDrop_, uint64 gasLimit_, uint32 version_) internal pure returns (Request) {\n        // Casts below are upcasts, so they are safe\n        return Request.wrap(uint192(gasDrop_) \u003c\u003c SHIFT_GAS_DROP | uint192(gasLimit_) \u003c\u003c SHIFT_GAS_LIMIT | version_);\n    }\n\n    /// @notice Wraps the padded encoded request into a Request-typed value.\n    /// @dev The \"padded\" request is simply an encoded request casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded requests\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedRequest) internal pure returns (Request) {\n        // Casting to uint192 will truncate the highest bits, which is the behavior we want\n        return Request.wrap(uint192(paddedRequest));\n    }\n\n    /// @notice Returns the requested of gas token to drop to the recipient.\n    function gasDrop(Request request) internal pure returns (uint96) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return uint96(Request.unwrap(request) \u003e\u003e SHIFT_GAS_DROP);\n    }\n\n    /// @notice Returns the requested minimum amount of gas units to supply for execution.\n    function gasLimit(Request request) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Request.unwrap(request) \u003e\u003e SHIFT_GAS_LIMIT);\n    }\n\n    /// @notice Returns the requested base message version to pass to the recipient.\n    function version(Request request) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Request.unwrap(request));\n    }\n}\n\n// node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        require(value \u003c= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        require(value \u003c= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        require(value \u003c= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value \u003c= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        require(value \u003c= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        require(value \u003c= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        require(value \u003c= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        require(value \u003c= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        require(value \u003c= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        require(value \u003c= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        require(value \u003c= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        require(value \u003c= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        require(value \u003c= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        require(value \u003c= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        require(value \u003c= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value \u003c= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        require(value \u003c= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        require(value \u003c= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        require(value \u003c= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value \u003c= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        require(value \u003c= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        require(value \u003c= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        require(value \u003c= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value \u003c= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        require(value \u003c= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        require(value \u003c= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        require(value \u003c= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value \u003c= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        require(value \u003c= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value \u003c= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value \u003c= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     *\n     * _Available since v3.0._\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value \u003e= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     *\n     * _Available since v3.0._\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value \u003c= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     *\n     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length \u003e 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance \u003e= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance \u003e= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length \u003e 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n\n// contracts/base/MultiCallable.sol\n\n/// @notice Collection of Multicall utilities. Fork of Multicall3:\n/// https://github.com/mds1/multicall/blob/master/src/Multicall3.sol\nabstract contract MultiCallable {\n    struct Call {\n        bool allowFailure;\n        bytes callData;\n    }\n\n    struct Result {\n        bool success;\n        bytes returnData;\n    }\n\n    /// @notice Aggregates a few calls to this contract into one multicall without modifying `msg.sender`.\n    function multicall(Call[] calldata calls) external returns (Result[] memory callResults) {\n        uint256 amount = calls.length;\n        callResults = new Result[](amount);\n        Call calldata call_;\n        for (uint256 i = 0; i \u003c amount;) {\n            call_ = calls[i];\n            Result memory result = callResults[i];\n            // We perform a delegate call to ourselves here. Delegate call does not modify `msg.sender`, so\n            // this will have the same effect as if `msg.sender` performed all the calls themselves one by one.\n            // solhint-disable-next-line avoid-low-level-calls\n            (result.success, result.returnData) = address(this).delegatecall(call_.callData);\n            // solhint-disable-next-line no-inline-assembly\n            assembly {\n                // Revert if the call fails and failure is not allowed\n                // `allowFailure := calldataload(call_)` and `success := mload(result)`\n                if iszero(or(calldataload(call_), mload(result))) {\n                    // Revert with `0x4d6a2328` (function selector for `MulticallFailed()`)\n                    mstore(0x00, 0x4d6a232800000000000000000000000000000000000000000000000000000000)\n                    revert(0x00, 0x04)\n                }\n            }\n            unchecked {\n                ++i;\n            }\n        }\n    }\n}\n\n// contracts/base/Version.sol\n\n/**\n * @title Versioned\n * @notice Version getter for contracts. Doesn't use any storage slots, meaning\n * it will never cause any troubles with the upgradeable contracts. For instance, this contract\n * can be added or removed from the inheritance chain without shifting the storage layout.\n */\nabstract contract Versioned {\n    /**\n     * @notice Struct that is mimicking the storage layout of a string with 32 bytes or less.\n     * Length is limited by 32, so the whole string payload takes two memory words:\n     * @param length    String length\n     * @param data      String characters\n     */\n    struct _ShortString {\n        uint256 length;\n        bytes32 data;\n    }\n\n    /// @dev Length of the \"version string\"\n    uint256 private immutable _length;\n    /// @dev Bytes representation of the \"version string\".\n    /// Strings with length over 32 are not supported!\n    bytes32 private immutable _data;\n\n    constructor(string memory version_) {\n        _length = bytes(version_).length;\n        if (_length \u003e 32) revert IncorrectVersionLength();\n        // bytes32 is left-aligned =\u003e this will store the byte representation of the string\n        // with the trailing zeroes to complete the 32-byte word\n        _data = bytes32(bytes(version_));\n    }\n\n    function version() external view returns (string memory versionString) {\n        // Load the immutable values to form the version string\n        _ShortString memory str = _ShortString(_length, _data);\n        // The only way to do this cast is doing some dirty assembly\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            versionString := str\n        }\n    }\n}\n\n// contracts/libs/ChainContext.sol\n\n/// @notice Library for accessing chain context variables as tightly packed integers.\n/// Messaging contracts should rely on this library for accessing chain context variables\n/// instead of doing the casting themselves.\nlibrary ChainContext {\n    using SafeCast for uint256;\n\n    /// @notice Returns the current block number as uint40.\n    /// @dev Reverts if block number is greater than 40 bits, which is not supposed to happen\n    /// until the block.timestamp overflows (assuming block time is at least 1 second).\n    function blockNumber() internal view returns (uint40) {\n        return block.number.toUint40();\n    }\n\n    /// @notice Returns the current block timestamp as uint40.\n    /// @dev Reverts if block timestamp is greater than 40 bits, which is\n    /// supposed to happen approximately in year 36835.\n    function blockTimestamp() internal view returns (uint40) {\n        return block.timestamp.toUint40();\n    }\n\n    /// @notice Returns the chain id as uint32.\n    /// @dev Reverts if chain id is greater than 32 bits, which is not\n    /// supposed to happen in production.\n    function chainId() internal view returns (uint32) {\n        return block.chainid.toUint32();\n    }\n}\n\n// contracts/libs/Structures.sol\n\n// Here we define common enums and structures to enable their easier reusing later.\n\n// ═══════════════════════════════ AGENT STATUS ════════════════════════════════\n\n/// @dev Potential statuses for the off-chain bonded agent:\n/// - Unknown: never provided a bond =\u003e signature not valid\n/// - Active: has a bond in BondingManager =\u003e signature valid\n/// - Unstaking: has a bond in BondingManager, initiated the unstaking =\u003e signature not valid\n/// - Resting: used to have a bond in BondingManager, successfully unstaked =\u003e signature not valid\n/// - Fraudulent: proven to commit fraud, value in Merkle Tree not updated =\u003e signature not valid\n/// - Slashed: proven to commit fraud, value in Merkle Tree was updated =\u003e signature not valid\n/// Unstaked agent could later be added back to THE SAME domain by staking a bond again.\n/// Honest agent: Unknown -\u003e Active -\u003e unstaking -\u003e Resting -\u003e Active ...\n/// Malicious agent: Unknown -\u003e Active -\u003e Fraudulent -\u003e Slashed\n/// Malicious agent: Unknown -\u003e Active -\u003e Unstaking -\u003e Fraudulent -\u003e Slashed\nenum AgentFlag {\n    Unknown,\n    Active,\n    Unstaking,\n    Resting,\n    Fraudulent,\n    Slashed\n}\n\n/// @notice Struct for storing an agent in the BondingManager contract.\nstruct AgentStatus {\n    AgentFlag flag;\n    uint32 domain;\n    uint32 index;\n}\n// 184 bits available for tight packing\n\nusing StructureUtils for AgentStatus global;\n\n/// @notice Potential statuses of an agent in terms of being in dispute\n/// - None: agent is not in dispute\n/// - Pending: agent is in unresolved dispute\n/// - Slashed: agent was in dispute that lead to agent being slashed\n/// Note: agent who won the dispute has their status reset to None\nenum DisputeFlag {\n    None,\n    Pending,\n    Slashed\n}\n\n/// @notice Struct for storing dispute status of an agent.\n/// @param flag         Dispute flag: None/Pending/Slashed.\n/// @param openedAt     Timestamp when the latest agent dispute was opened (zero if not opened).\n/// @param resolvedAt   Timestamp when the latest agent dispute was resolved (zero if not resolved).\nstruct DisputeStatus {\n    DisputeFlag flag;\n    uint40 openedAt;\n    uint40 resolvedAt;\n}\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\n/// @notice Struct representing the status of Destination contract.\n/// @param snapRootTime     Timestamp when latest snapshot root was accepted\n/// @param agentRootTime    Timestamp when latest agent root was accepted\n/// @param notaryIndex      Index of Notary who signed the latest agent root\nstruct DestinationStatus {\n    uint40 snapRootTime;\n    uint40 agentRootTime;\n    uint32 notaryIndex;\n}\n\n// ═══════════════════════════════ EXECUTION HUB ═══════════════════════════════\n\n/// @notice Potential statuses of the message in Execution Hub.\n/// - None: there hasn't been a valid attempt to execute the message yet\n/// - Failed: there was a valid attempt to execute the message, but recipient reverted\n/// - Success: there was a valid attempt to execute the message, and recipient did not revert\n/// Note: message can be executed until its status is Success\nenum MessageStatus {\n    None,\n    Failed,\n    Success\n}\n\nlibrary StructureUtils {\n    /// @notice Checks that Agent is Active\n    function verifyActive(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active) {\n            revert AgentNotActive();\n        }\n    }\n\n    /// @notice Checks that Agent is Unstaking\n    function verifyUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Unstaking) {\n            revert AgentNotUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Active or Unstaking\n    function verifyActiveUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active \u0026\u0026 status.flag != AgentFlag.Unstaking) {\n            revert AgentNotActiveNorUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Fraudulent\n    function verifyFraudulent(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Fraudulent) {\n            revert AgentNotFraudulent();\n        }\n    }\n\n    /// @notice Checks that Agent is not Unknown\n    function verifyKnown(AgentStatus memory status) internal pure {\n        if (status.flag == AgentFlag.Unknown) {\n            revert AgentUnknown();\n        }\n    }\n}\n\n// contracts/libs/memory/MemView.sol\n\n/// @dev MemView is an untyped view over a portion of memory to be used instead of `bytes memory`\ntype MemView is uint256;\n\n/// @dev Attach library functions to MemView\nusing MemViewLib for MemView global;\n\n/// @notice Library for operations with the memory views.\n/// Forked from https://github.com/summa-tx/memview-sol with several breaking changes:\n/// - The codebase is ported to Solidity 0.8\n/// - Custom errors are added\n/// - The runtime type checking is replaced with compile-time check provided by User-Defined Value Types\n///   https://docs.soliditylang.org/en/latest/types.html#user-defined-value-types\n/// - uint256 is used as the underlying type for the \"memory view\" instead of bytes29.\n///   It is wrapped into MemView custom type in order not to be confused with actual integers.\n/// - Therefore the \"type\" field is discarded, allowing to allocate 16 bytes for both view location and length\n/// - The documentation is expanded\n/// - Library functions unused by the rest of the codebase are removed\n//  - Very pretty code separators are added :)\nlibrary MemViewLib {\n    /// @notice Stack layout for uint256 (from highest bits to lowest)\n    /// (32 .. 16]      loc     16 bytes    Memory address of underlying bytes\n    /// (16 .. 00]      len     16 bytes    Length of underlying bytes\n\n    // ═══════════════════════════════════════════ BUILDING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Instantiate a new untyped memory view. This should generally not be called directly.\n     * Prefer `ref` wherever possible.\n     * @param loc_          The memory address\n     * @param len_          The length\n     * @return The new view with the specified location and length\n     */\n    function build(uint256 loc_, uint256 len_) internal pure returns (MemView) {\n        uint256 end_ = loc_ + len_;\n        // Make sure that a view is not constructed that points to unallocated memory\n        // as this could be indicative of a buffer overflow attack\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            if gt(end_, mload(0x40)) { end_ := 0 }\n        }\n        if (end_ == 0) {\n            revert UnallocatedMemory();\n        }\n        return _unsafeBuildUnchecked(loc_, len_);\n    }\n\n    /**\n     * @notice Instantiate a memory view from a byte array.\n     * @dev Note that due to Solidity memory representation, it is not possible to\n     * implement a deref, as the `bytes` type stores its len in memory.\n     * @param arr           The byte array\n     * @return The memory view over the provided byte array\n     */\n    function ref(bytes memory arr) internal pure returns (MemView) {\n        uint256 len_ = arr.length;\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 loc_;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // We add 0x20, so that the view starts exactly where the array data starts\n            loc_ := add(arr, 0x20)\n        }\n        return build(loc_, len_);\n    }\n\n    // ════════════════════════════════════════════ CLONING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to the new memory.\n     * @param memView       The memory view\n     * @return arr          The cloned byte array\n     */\n    function clone(MemView memView) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        unchecked {\n            _unsafeCopyTo(memView, ptr + 0x20);\n        }\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 len_ = memView.len();\n        uint256 footprint_ = memView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    /**\n     * @notice Copies all views, joins them into a new bytearray.\n     * @param memViews      The memory views\n     * @return arr          The new byte array with joined data behind the given views\n     */\n    function join(MemView[] memory memViews) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        MemView newView;\n        unchecked {\n            newView = _unsafeJoin(memViews, ptr + 0x20);\n        }\n        uint256 len_ = newView.len();\n        uint256 footprint_ = newView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    // ══════════════════════════════════════════ INSPECTING MEMORY VIEW ═══════════════════════════════════════════════\n\n    /**\n     * @notice Returns the memory address of the underlying bytes.\n     * @param memView       The memory view\n     * @return loc_         The memory address\n     */\n    function loc(MemView memView) internal pure returns (uint256 loc_) {\n        // loc is stored in the highest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u003e\u003e 128;\n    }\n\n    /**\n     * @notice Returns the number of bytes of the view.\n     * @param memView       The memory view\n     * @return len_         The length of the view\n     */\n    function len(MemView memView) internal pure returns (uint256 len_) {\n        // len is stored in the lowest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u0026 type(uint128).max;\n    }\n\n    /**\n     * @notice Returns the endpoint of `memView`.\n     * @param memView       The memory view\n     * @return end_         The endpoint of `memView`\n     */\n    function end(MemView memView) internal pure returns (uint256 end_) {\n        // The endpoint never overflows uint128, let alone uint256, so we could use unchecked math here\n        unchecked {\n            return memView.loc() + memView.len();\n        }\n    }\n\n    /**\n     * @notice Returns the number of memory words this memory view occupies, rounded up.\n     * @param memView       The memory view\n     * @return words_       The number of memory words\n     */\n    function words(MemView memView) internal pure returns (uint256 words_) {\n        // returning ceil(length / 32.0)\n        unchecked {\n            return (memView.len() + 31) \u003e\u003e 5;\n        }\n    }\n\n    /**\n     * @notice Returns the in-memory footprint of a fresh copy of the view.\n     * @param memView       The memory view\n     * @return footprint_   The in-memory footprint of a fresh copy of the view.\n     */\n    function footprint(MemView memView) internal pure returns (uint256 footprint_) {\n        // words() * 32\n        return memView.words() \u003c\u003c 5;\n    }\n\n    // ════════════════════════════════════════════ HASHING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the keccak256 hash of the underlying memory\n     * @param memView       The memory view\n     * @return digest       The keccak256 hash of the underlying memory\n     */\n    function keccak(MemView memView) internal pure returns (bytes32 digest) {\n        uint256 loc_ = memView.loc();\n        uint256 len_ = memView.len();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            digest := keccak256(loc_, len_)\n        }\n    }\n\n    /**\n     * @notice Adds a salt to the keccak256 hash of the underlying data and returns the keccak256 hash of the\n     * resulting data.\n     * @param memView       The memory view\n     * @return digestSalted keccak256(salt, keccak256(memView))\n     */\n    function keccakSalted(MemView memView, bytes32 salt) internal pure returns (bytes32 digestSalted) {\n        return keccak256(bytes.concat(salt, memView.keccak()));\n    }\n\n    // ════════════════════════════════════════════ SLICING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Safe slicing without memory modification.\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the given index\n     */\n    function slice(MemView memView, uint256 index_, uint256 len_) internal pure returns (MemView) {\n        uint256 loc_ = memView.loc();\n        // Ensure it doesn't overrun the view\n        if (loc_ + index_ + len_ \u003e memView.end()) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // loc_ + index_ \u003c= memView.end()\n            return build({loc_: loc_ + index_, len_: len_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing bytes from `index` to end(memView).\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @return The new view for the slice starting from the given index until the initial view endpoint\n     */\n    function sliceFrom(MemView memView, uint256 index_) internal pure returns (MemView) {\n        uint256 len_ = memView.len();\n        // Ensure it doesn't overrun the view\n        if (index_ \u003e len_) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // index_ \u003c= len_ =\u003e memView.loc() + index_ \u003c= memView.loc() + memView.len() == memView.end()\n            return build({loc_: memView.loc() + index_, len_: len_ - index_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the first `len` bytes.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the initial view beginning\n     */\n    function prefix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        return memView.slice({index_: 0, len_: len_});\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the last `len` byte.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length until the initial view endpoint\n     */\n    function postfix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        uint256 viewLen = memView.len();\n        // Ensure it doesn't overrun the view\n        if (len_ \u003e viewLen) {\n            revert ViewOverrun();\n        }\n        // Could do the unchecked math due to the check above\n        uint256 index_;\n        unchecked {\n            index_ = viewLen - len_;\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // len_ \u003c= memView.len() =\u003e memView.loc() \u003c= loc_ \u003c= memView.end()\n            return build({loc_: memView.loc() + viewLen - len_, len_: len_});\n        }\n    }\n\n    // ═══════════════════════════════════════════ INDEXING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Load up to 32 bytes from the view onto the stack.\n     * @dev Returns a bytes32 with only the `bytes_` HIGHEST bytes set.\n     * This can be immediately cast to a smaller fixed-length byte array.\n     * To automatically cast to an integer, use `indexUint`.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return result       The 32 byte result having only `bytes_` highest bytes set\n     */\n    function index(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (bytes32 result) {\n        if (bytes_ == 0) {\n            return bytes32(0);\n        }\n        // Can't load more than 32 bytes to the stack in one go\n        if (bytes_ \u003e 32) {\n            revert IndexedTooMuch();\n        }\n        // The last indexed byte should be within view boundaries\n        if (index_ + bytes_ \u003e memView.len()) {\n            revert ViewOverrun();\n        }\n        uint256 bitLength = bytes_ \u003c\u003c 3; // bytes_ * 8\n        uint256 loc_ = memView.loc();\n        // Get a mask with `bitLength` highest bits set\n        uint256 mask;\n        // 0x800...00 binary representation is 100...00\n        // sar stands for \"signed arithmetic shift\": https://en.wikipedia.org/wiki/Arithmetic_shift\n        // sar(N-1, 100...00) = 11...100..00, with exactly N highest bits set to 1\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            mask := sar(sub(bitLength, 1), 0x8000000000000000000000000000000000000000000000000000000000000000)\n        }\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load a full word using index offset, and apply mask to ignore non-relevant bytes\n            result := and(mload(add(loc_, index_)), mask)\n        }\n    }\n\n    /**\n     * @notice Parse an unsigned integer from the view at `index`.\n     * @dev Requires that the view have \u003e= `bytes_` bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return The unsigned integer\n     */\n    function indexUint(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (uint256) {\n        bytes32 indexedBytes = memView.index(index_, bytes_);\n        // `index()` returns left-aligned `bytes_`, while integers are right-aligned\n        // Shifting here to right-align with the full 32 bytes word: need to shift right `(32 - bytes_)` bytes\n        unchecked {\n            // memView.index() reverts when bytes_ \u003e 32, thus unchecked math\n            return uint256(indexedBytes) \u003e\u003e ((32 - bytes_) \u003c\u003c 3);\n        }\n    }\n\n    /**\n     * @notice Parse an address from the view at `index`.\n     * @dev Requires that the view have \u003e= 20 bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @return The address\n     */\n    function indexAddress(MemView memView, uint256 index_) internal pure returns (address) {\n        // index 20 bytes as `uint160`, and then cast to `address`\n        return address(uint160(memView.indexUint(index_, 20)));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns a memory view over the specified memory location\n    /// without checking if it points to unallocated memory.\n    function _unsafeBuildUnchecked(uint256 loc_, uint256 len_) private pure returns (MemView) {\n        // There is no scenario where loc or len would overflow uint128, so we omit this check.\n        // We use the highest 128 bits to encode the location and the lowest 128 bits to encode the length.\n        return MemView.wrap((loc_ \u003c\u003c 128) | len_);\n    }\n\n    /**\n     * @notice Copy the view to a location, return an unsafe memory reference\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memView       The memory view\n     * @param newLoc        The new location to copy the underlying view data\n     * @return The memory view over the unsafe memory with the copied underlying data\n     */\n    function _unsafeCopyTo(MemView memView, uint256 newLoc) private view returns (MemView) {\n        uint256 len_ = memView.len();\n        uint256 oldLoc = memView.loc();\n\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (newLoc \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        bool res;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // use the identity precompile (0x04) to copy\n            res := staticcall(gas(), 0x04, oldLoc, len_, newLoc, len_)\n        }\n        if (!res) revert PrecompileOutOfGas();\n        return _unsafeBuildUnchecked({loc_: newLoc, len_: len_});\n    }\n\n    /**\n     * @notice Join the views in memory, return an unsafe reference to the memory.\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memViews      The memory views\n     * @return The conjoined view pointing to the new memory\n     */\n    function _unsafeJoin(MemView[] memory memViews, uint256 location) private view returns (MemView) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (location \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        // Copy the views to the specified location one by one, by tracking the amount of copied bytes so far\n        uint256 offset = 0;\n        for (uint256 i = 0; i \u003c memViews.length;) {\n            MemView memView = memViews[i];\n            // We can use the unchecked math here as location + sum(view.length) will never overflow uint256\n            unchecked {\n                _unsafeCopyTo(memView, location + offset);\n                offset += memView.len();\n                ++i;\n            }\n        }\n        return _unsafeBuildUnchecked({loc_: location, len_: offset});\n    }\n}\n\n// contracts/libs/merkle/MerkleMath.sol\n\nlibrary MerkleMath {\n    // ═════════════════════════════════════════ BASIC MERKLE CALCULATIONS ═════════════════════════════════════════════\n\n    /**\n     * @notice Calculates the merkle root for the given leaf and merkle proof.\n     * @dev Will revert if proof length exceeds the tree height.\n     * @param index     Index of `leaf` in tree\n     * @param leaf      Leaf of the merkle tree\n     * @param proof     Proof of inclusion of `leaf` in the tree\n     * @param height    Height of the merkle tree\n     * @return root_    Calculated Merkle Root\n     */\n    function proofRoot(uint256 index, bytes32 leaf, bytes32[] memory proof, uint256 height)\n        internal\n        pure\n        returns (bytes32 root_)\n    {\n        // Proof length could not exceed the tree height\n        uint256 proofLen = proof.length;\n        if (proofLen \u003e height) revert TreeHeightTooLow();\n        root_ = leaf;\n        /// @dev Apply unchecked to all ++h operations\n        unchecked {\n            // Go up the tree levels from the leaf following the proof\n            for (uint256 h = 0; h \u003c proofLen; ++h) {\n                // Get a sibling node on current level: this is proof[h]\n                root_ = getParent(root_, proof[h], index, h);\n            }\n            // Go up to the root: the remaining siblings are EMPTY\n            for (uint256 h = proofLen; h \u003c height; ++h) {\n                root_ = getParent(root_, bytes32(0), index, h);\n            }\n        }\n    }\n\n    /**\n     * @notice Calculates the parent of a node on the path from one of the leafs to root.\n     * @param node          Node on a path from tree leaf to root\n     * @param sibling       Sibling for a given node\n     * @param leafIndex     Index of the tree leaf\n     * @param nodeHeight    \"Level height\" for `node` (ZERO for leafs, ORIGIN_TREE_HEIGHT for root)\n     */\n    function getParent(bytes32 node, bytes32 sibling, uint256 leafIndex, uint256 nodeHeight)\n        internal\n        pure\n        returns (bytes32 parent)\n    {\n        // Index for `node` on its \"tree level\" is (leafIndex / 2**height)\n        // \"Left child\" has even index, \"right child\" has odd index\n        if ((leafIndex \u003e\u003e nodeHeight) \u0026 1 == 0) {\n            // Left child\n            return getParent(node, sibling);\n        } else {\n            // Right child\n            return getParent(sibling, node);\n        }\n    }\n\n    /// @notice Calculates the parent of tow nodes in the merkle tree.\n    /// @dev We use implementation with H(0,0) = 0\n    /// This makes EVERY empty node in the tree equal to ZERO,\n    /// saving us from storing H(0,0), H(H(0,0), H(0, 0)), and so on\n    /// @param leftChild    Left child of the calculated node\n    /// @param rightChild   Right child of the calculated node\n    /// @return parent      Value for the node having above mentioned children\n    function getParent(bytes32 leftChild, bytes32 rightChild) internal pure returns (bytes32 parent) {\n        if (leftChild == bytes32(0) \u0026\u0026 rightChild == bytes32(0)) {\n            return 0;\n        } else {\n            return keccak256(bytes.concat(leftChild, rightChild));\n        }\n    }\n\n    // ════════════════════════════════ ROOT/PROOF CALCULATION FOR A LIST OF LEAFS ═════════════════════════════════════\n\n    /**\n     * @notice Calculates merkle root for a list of given leafs.\n     * Merkle Tree is constructed by padding the list with ZERO values for leafs until list length is `2**height`.\n     * Merkle Root is calculated for the constructed tree, and then saved in `leafs[0]`.\n     * \u003e Note:\n     * \u003e - `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * \u003e - Caller is expected not to reuse `hashes` list after the call, and only use `leafs[0]` value,\n     * which is guaranteed to contain the calculated merkle root.\n     * \u003e - root is calculated using the `H(0,0) = 0` Merkle Tree implementation. See MerkleTree.sol for details.\n     * @dev Amount of leaves should be at most `2**height`\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param height    Height of the Merkle Tree to construct\n     */\n    function calculateRoot(bytes32[] memory hashes, uint256 height) internal pure {\n        uint256 levelLength = hashes.length;\n        // Amount of hashes could not exceed amount of leafs in tree with the given height\n        if (levelLength \u003e (1 \u003c\u003c height)) revert TreeHeightTooLow();\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\": the amount of iterations for the for loop above.\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n            }\n        }\n    }\n\n    /**\n     * @notice Generates a proof of inclusion of a leaf in the list. If the requested index is outside\n     * of the list range, generates a proof of inclusion for an empty leaf (proof of non-inclusion).\n     * The Merkle Tree is constructed by padding the list with ZERO values until list length is a power of two\n     * __AND__ index is in the extended list range. For example:\n     *  - `hashes.length == 6` and `0 \u003c= index \u003c= 7` will \"extend\" the list to 8 entries.\n     *  - `hashes.length == 6` and `7 \u003c index \u003c= 15` will \"extend\" the list to 16 entries.\n     * \u003e Note: `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * Caller is expected not to reuse `hashes` list after the call.\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param index     Leaf index to generate the proof for\n     * @return proof    Generated merkle proof\n     */\n    function calculateProof(bytes32[] memory hashes, uint256 index) internal pure returns (bytes32[] memory proof) {\n        // Use only meaningful values for the shortened proof\n        // Check if index is within the list range (we want to generates proofs for outside leafs as well)\n        uint256 height = getHeight(index \u003c hashes.length ? hashes.length : (index + 1));\n        proof = new bytes32[](height);\n        uint256 levelLength = hashes.length;\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Use sibling for the merkle proof; `index^1` is index of our sibling\n                proof[h] = (index ^ 1 \u003c levelLength) ? hashes[index ^ 1] : bytes32(0);\n\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\"\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n                // Traverse to parent node\n                index \u003e\u003e= 1;\n            }\n        }\n    }\n\n    /// @notice Returns the height of the tree having a given amount of leafs.\n    function getHeight(uint256 leafs) internal pure returns (uint256 height) {\n        uint256 amount = 1;\n        while (amount \u003c leafs) {\n            unchecked {\n                ++height;\n            }\n            amount \u003c\u003c= 1;\n        }\n    }\n}\n\n// contracts/libs/stack/GasData.sol\n\n/// GasData in encoded data with \"basic information about gas prices\" for some chain.\ntype GasData is uint96;\n\nusing GasDataLib for GasData global;\n\n/// ChainGas is encoded data with given chain's \"basic information about gas prices\".\ntype ChainGas is uint128;\n\nusing GasDataLib for ChainGas global;\n\n/// Library for encoding and decoding GasData and ChainGas structs.\n/// # GasData\n/// `GasData` is a struct to store the \"basic information about gas prices\", that could\n/// be later used to approximate the cost of a message execution, and thus derive the\n/// minimal tip values for sending a message to the chain.\n/// \u003e - `GasData` is supposed to be cached by `GasOracle` contract, allowing to store the\n/// \u003e approximates instead of the exact values, and thus save on storage costs.\n/// \u003e - For instance, if `GasOracle` only updates the values on +- 10% change, having an\n/// \u003e 0.4% error on the approximates would be acceptable.\n/// `GasData` is supposed to be included in the Origin's state, which are synced across\n/// chains using Agent-signed snapshots and attestations.\n/// ## GasData stack layout (from highest bits to lowest)\n///\n/// | Position   | Field        | Type   | Bytes | Description                                         |\n/// | ---------- | ------------ | ------ | ----- | --------------------------------------------------- |\n/// | (012..010] | gasPrice     | uint16 | 2     | Gas price for the chain (in Wei per gas unit)       |\n/// | (010..008] | dataPrice    | uint16 | 2     | Calldata price (in Wei per byte of content)         |\n/// | (008..006] | execBuffer   | uint16 | 2     | Tx fee safety buffer for message execution (in Wei) |\n/// | (006..004] | amortAttCost | uint16 | 2     | Amortized cost for attestation submission (in Wei)  |\n/// | (004..002] | etherPrice   | uint16 | 2     | Chain's Ether Price / Mainnet Ether Price (in BWAD) |\n/// | (002..000] | markup       | uint16 | 2     | Markup for the message execution (in BWAD)          |\n/// \u003e See Number.sol for more details on `Number` type and BWAD (binary WAD) math.\n///\n/// ## ChainGas stack layout (from highest bits to lowest)\n///\n/// | Position   | Field   | Type   | Bytes | Description      |\n/// | ---------- | ------- | ------ | ----- | ---------------- |\n/// | (016..004] | gasData | uint96 | 12    | Chain's gas data |\n/// | (004..000] | domain  | uint32 | 4     | Chain's domain   |\nlibrary GasDataLib {\n    /// @dev Amount of bits to shift to gasPrice field\n    uint96 private constant SHIFT_GAS_PRICE = 10 * 8;\n    /// @dev Amount of bits to shift to dataPrice field\n    uint96 private constant SHIFT_DATA_PRICE = 8 * 8;\n    /// @dev Amount of bits to shift to execBuffer field\n    uint96 private constant SHIFT_EXEC_BUFFER = 6 * 8;\n    /// @dev Amount of bits to shift to amortAttCost field\n    uint96 private constant SHIFT_AMORT_ATT_COST = 4 * 8;\n    /// @dev Amount of bits to shift to etherPrice field\n    uint96 private constant SHIFT_ETHER_PRICE = 2 * 8;\n\n    /// @dev Amount of bits to shift to gasData field\n    uint128 private constant SHIFT_GAS_DATA = 4 * 8;\n\n    // ═════════════════════════════════════════════════ GAS DATA ══════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded GasData struct with the given fields.\n    /// @param gasPrice_        Gas price for the chain (in Wei per gas unit)\n    /// @param dataPrice_       Calldata price (in Wei per byte of content)\n    /// @param execBuffer_      Tx fee safety buffer for message execution (in Wei)\n    /// @param amortAttCost_    Amortized cost for attestation submission (in Wei)\n    /// @param etherPrice_      Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n    /// @param markup_          Markup for the message execution (in BWAD)\n    function encodeGasData(\n        Number gasPrice_,\n        Number dataPrice_,\n        Number execBuffer_,\n        Number amortAttCost_,\n        Number etherPrice_,\n        Number markup_\n    ) internal pure returns (GasData) {\n        // Number type wraps uint16, so could safely be casted to uint96\n        // forgefmt: disable-next-item\n        return GasData.wrap(\n            uint96(Number.unwrap(gasPrice_)) \u003c\u003c SHIFT_GAS_PRICE |\n            uint96(Number.unwrap(dataPrice_)) \u003c\u003c SHIFT_DATA_PRICE |\n            uint96(Number.unwrap(execBuffer_)) \u003c\u003c SHIFT_EXEC_BUFFER |\n            uint96(Number.unwrap(amortAttCost_)) \u003c\u003c SHIFT_AMORT_ATT_COST |\n            uint96(Number.unwrap(etherPrice_)) \u003c\u003c SHIFT_ETHER_PRICE |\n            uint96(Number.unwrap(markup_))\n        );\n    }\n\n    /// @notice Wraps padded uint256 value into GasData struct.\n    function wrapGasData(uint256 paddedGasData) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(paddedGasData));\n    }\n\n    /// @notice Returns the gas price, in Wei per gas unit.\n    function gasPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_GAS_PRICE));\n    }\n\n    /// @notice Returns the calldata price, in Wei per byte of content.\n    function dataPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_DATA_PRICE));\n    }\n\n    /// @notice Returns the tx fee safety buffer for message execution, in Wei.\n    function execBuffer(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_EXEC_BUFFER));\n    }\n\n    /// @notice Returns the amortized cost for attestation submission, in Wei.\n    function amortAttCost(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_AMORT_ATT_COST));\n    }\n\n    /// @notice Returns the ratio of Chain's Ether Price / Mainnet Ether Price, in BWAD math.\n    function etherPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_ETHER_PRICE));\n    }\n\n    /// @notice Returns the markup for the message execution, in BWAD math.\n    function markup(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data)));\n    }\n\n    // ════════════════════════════════════════════════ CHAIN DATA ═════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded ChainGas struct with the given fields.\n    /// @param gasData_ Chain's gas data\n    /// @param domain_  Chain's domain\n    function encodeChainGas(GasData gasData_, uint32 domain_) internal pure returns (ChainGas) {\n        // GasData type wraps uint96, so could safely be casted to uint128\n        return ChainGas.wrap(uint128(GasData.unwrap(gasData_)) \u003c\u003c SHIFT_GAS_DATA | uint128(domain_));\n    }\n\n    /// @notice Wraps padded uint256 value into ChainGas struct.\n    function wrapChainGas(uint256 paddedChainGas) internal pure returns (ChainGas) {\n        // Casting to uint128 will truncate the highest bits, which is the behavior we want\n        return ChainGas.wrap(uint128(paddedChainGas));\n    }\n\n    /// @notice Returns the chain's gas data.\n    function gasData(ChainGas data) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(ChainGas.unwrap(data) \u003e\u003e SHIFT_GAS_DATA));\n    }\n\n    /// @notice Returns the chain's domain.\n    function domain(ChainGas data) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(ChainGas.unwrap(data));\n    }\n\n    /// @notice Returns the hash for the list of ChainGas structs.\n    function snapGasHash(ChainGas[] memory snapGas) internal pure returns (bytes32 snapGasHash_) {\n        // Use assembly to calculate the hash of the array without copying it\n        // ChainGas takes a single word of storage, thus ChainGas[] is stored in the following way:\n        // 0x00: length of the array, in words\n        // 0x20: first ChainGas struct\n        // 0x40: second ChainGas struct\n        // And so on...\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Find the location where the array data starts, we add 0x20 to skip the length field\n            let loc := add(snapGas, 0x20)\n            // Load the length of the array (in words).\n            // Shifting left 5 bits is equivalent to multiplying by 32: this converts from words to bytes.\n            let len := shl(5, mload(snapGas))\n            // Calculate the hash of the array\n            snapGasHash_ := keccak256(loc, len)\n        }\n    }\n}\n\n// contracts/libs/stack/Header.sol\n\n/// Header is encoded data with \"general routing information\".\ntype Header is uint136;\n\nusing HeaderLib for Header global;\n\n/// Types of messages supported by Origin-Destination\n/// - Base: message sent by protocol user, contains tips\n/// - Manager: message sent between AgentManager contracts located on different chains, no tips\nenum MessageFlag {\n    Base,\n    Manager\n}\n\nusing HeaderLib for MessageFlag global;\n\n/// Library for formatting _the header part_ of _the messages used by Origin and Destination_.\n/// - Header represents general information for routing a Message for Origin and Destination.\n/// - Header occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n///\n/// # Header stack layout (from highest bits to lowest)\n///\n/// | Position   | Field            | Type   | Bytes | Description                             |\n/// | ---------- | ---------------- | ------ | ----- | --------------------------------------- |\n/// | (017..016] | flag             | uint8  | 1     | Flag specifying the type of message     |\n/// | (016..012] | origin           | uint32 | 4     | Domain where message originated         |\n/// | (012..008] | nonce            | uint32 | 4     | Message nonce on the origin domain      |\n/// | (008..004] | destination      | uint32 | 4     | Domain where message will be executed   |\n/// | (004..000] | optimisticPeriod | uint32 | 4     | Optimistic period that will be enforced |\nlibrary HeaderLib {\n    /// @dev Amount of bits to shift to flag field\n    uint136 private constant SHIFT_FLAG = 16 * 8;\n    /// @dev Amount of bits to shift to origin field\n    uint136 private constant SHIFT_ORIGIN = 12 * 8;\n    /// @dev Amount of bits to shift to nonce field\n    uint136 private constant SHIFT_NONCE = 8 * 8;\n    /// @dev Amount of bits to shift to destination field\n    uint136 private constant SHIFT_DESTINATION = 4 * 8;\n\n    /// @notice Returns an encoded header with provided fields\n    /// @param origin_              Domain of origin chain\n    /// @param nonce_               Message nonce on origin chain\n    /// @param destination_         Domain of destination chain\n    /// @param optimisticPeriod_    Optimistic period for message execution\n    function encodeHeader(\n        MessageFlag flag_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint32 destination_,\n        uint32 optimisticPeriod_\n    ) internal pure returns (Header) {\n        // All casts below are upcasts, so they are safe\n        // forgefmt: disable-next-item\n        return Header.wrap(\n            uint136(uint8(flag_)) \u003c\u003c SHIFT_FLAG |\n            uint136(origin_) \u003c\u003c SHIFT_ORIGIN |\n            uint136(nonce_) \u003c\u003c SHIFT_NONCE |\n            uint136(destination_) \u003c\u003c SHIFT_DESTINATION |\n            uint136(optimisticPeriod_)\n        );\n    }\n\n    /// @notice Checks that the header is a valid encoded header.\n    function isHeader(uint256 paddedHeader) internal pure returns (bool) {\n        // Check that flag is within range\n        return _flag(paddedHeader) \u003c= uint8(type(MessageFlag).max);\n    }\n\n    /// @notice Wraps the padded encoded request into a Header-typed value.\n    /// @dev The \"padded\" header is simply an encoded header casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded headers\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedHeader) internal pure returns (Header) {\n        // Check that flag is within range\n        if (!isHeader(paddedHeader)) revert FlagOutOfRange();\n        // Casting to uint136 will truncate the highest bits, which is the behavior we want\n        return Header.wrap(uint136(paddedHeader));\n    }\n\n    /// @notice Returns header's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Header header) internal pure returns (bytes32 hashedHeader) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store header in scratch space\n            mstore(0, header)\n            // Compute hash of header padded to 32 bytes\n            hashedHeader := keccak256(0, 32)\n        }\n    }\n\n    // ══════════════════════════════════════════════ HEADER SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns header's flag field\n    function flag(Header header) internal pure returns (MessageFlag) {\n        // We check that flag is within range when wrapping the header, so this cast is safe\n        return MessageFlag(_flag(Header.unwrap(header)));\n    }\n\n    /// @notice Returns header's origin field\n    function origin(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_ORIGIN);\n    }\n\n    /// @notice Returns header's nonce field\n    function nonce(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_NONCE);\n    }\n\n    /// @notice Returns header's destination field\n    function destination(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_DESTINATION);\n    }\n\n    /// @notice Returns header's optimistic seconds field\n    function optimisticPeriod(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns header's flag field without casting to MessageFlag\n    function _flag(uint256 paddedHeader) private pure returns (uint8) {\n        // Casting to uint8 will truncate the highest bits, which is the behavior we want\n        return uint8(paddedHeader \u003e\u003e SHIFT_FLAG);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n     * constructor.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall \u0026\u0026 _initialized \u003c 1) || (!AddressUpgradeable.isContract(address(this)) \u0026\u0026 _initialized == 1),\n            \"Initializable: contract is already initialized\"\n        );\n        _initialized = 1;\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: setting the version to 255 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing \u0026\u0026 _initialized \u003c version, \"Initializable: contract is already initialized\");\n        _initialized = version;\n        _initializing = true;\n        _;\n        _initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        require(_initializing, \"Initializable: contract is not initializing\");\n        _;\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized != type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint8) {\n        return _initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _initializing;\n    }\n}\n\n// contracts/interfaces/IAgentManager.sol\n\ninterface IAgentManager {\n    /**\n     * @notice Allows Inbox to open a Dispute between a Guard and a Notary, if they are both not in Dispute already.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Guard or Notary is already in Dispute.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Allows Inbox to slash an agent, if their fraud was proven.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Domain doesn't match the saved agent domain.\n     * @param domain    Domain where the Agent is active\n     * @param agent     Address of the Agent\n     * @param prover    Address that initially provided fraud proof\n     */\n    function slashAgent(uint32 domain, address agent, address prover) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest known root of the Agent Merkle Tree.\n     */\n    function agentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns the number of opened Disputes.\n     * @dev This includes the Disputes that have been resolved already.\n     */\n    function getDisputesAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns information about the dispute with the given index.\n     * @dev Will revert if dispute with given index hasn't been opened yet.\n     * @param index             Dispute index\n     * @return guard            Address of the Guard in the Dispute\n     * @return notary           Address of the Notary in the Dispute\n     * @return slashedAgent     Address of the Agent who was slashed when Dispute was resolved\n     * @return fraudProver      Address who provided fraud proof to resolve the Dispute\n     * @return reportPayload    Raw payload with report data that led to the Dispute\n     * @return reportSignature  Guard signature for the report payload\n     */\n    function getDispute(uint256 index)\n        external\n        view\n        returns (\n            address guard,\n            address notary,\n            address slashedAgent,\n            address fraudProver,\n            bytes memory reportPayload,\n            bytes memory reportSignature\n        );\n\n    /**\n     * @notice Returns the current Dispute status of a given agent. See Structures.sol for details.\n     * @dev Every returned value will be set to zero if agent was not slashed and is not in Dispute.\n     * `rival` and `disputePtr` will be set to zero if the agent was slashed without being in Dispute.\n     * @param agent         Agent address\n     * @return flag         Flag describing the current Dispute status for the agent: None/Pending/Slashed\n     * @return rival        Address of the rival agent in the Dispute\n     * @return fraudProver  Address who provided fraud proof to resolve the Dispute\n     * @return disputePtr   Index of the opened Dispute PLUS ONE. Zero if agent is not in Dispute.\n     */\n    function disputeStatus(address agent)\n        external\n        view\n        returns (DisputeFlag flag, address rival, address fraudProver, uint256 disputePtr);\n}\n\n// contracts/interfaces/IAgentSecured.sol\n\ninterface IAgentSecured {\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * between a Guard and a Notary has been opened.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * has been resolved due to one of the agents being slashed.\n     * \u003e `rivalIndex` will be ZERO, if the slashed agent was not in the Dispute.\n     * @param slashedIndex  Index of the slashed agent in the Agent Merkle Tree\n     * @param rivalIndex    Index of the their Dispute Rival in the Agent Merkle Tree\n     */\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the address of the local AgentManager contract, which is treated as\n     * the \"source of truth\" for agent statuses.\n     */\n    function agentManager() external view returns (address);\n\n    /**\n     * @notice Returns the address of the local Inbox contract, which is treated as\n     * the \"source of truth\" for agent-signed statements.\n     * @dev Inbox passes verified agent statements to `IAgentSecured` contract.\n     */\n    function inbox() external view returns (address);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns (flag, openedAt, resolvedAt) that describes the latest status of\n     * the latest dispute for an agent with a given index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param agentIndex    Agent index in the Agent Merkle Tree\n     * @return              Latest dispute status for the given agent: (flag, openedAt, resolvedAt)\n     */\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory);\n}\n\n// contracts/libs/memory/ByteString.sol\n\n/// @dev CallData is a memory view over the payload to be used for an external call, i.e.\n/// recipient.call(callData). Its length is always (4 + 32 * N) bytes:\n/// - First 4 bytes represent the function selector.\n/// - 32 * N bytes represent N words that function arguments occupy.\ntype CallData is uint256;\n\n/// @dev Attach library functions to CallData\nusing ByteString for CallData global;\n\n/// @dev Signature is a memory view over a \"65 bytes\" array representing a ECDSA signature.\ntype Signature is uint256;\n\n/// @dev Attach library functions to Signature\nusing ByteString for Signature global;\n\nlibrary ByteString {\n    using MemViewLib for bytes;\n\n    /**\n     * @dev non-compact ECDSA signatures are enforced as of OZ 4.7.3\n     *\n     *      Signature payload memory layout\n     * [000 .. 032) r   bytes32 32 bytes\n     * [032 .. 064) s   bytes32 32 bytes\n     * [064 .. 065) v   uint8    1 byte\n     */\n    uint256 internal constant SIGNATURE_LENGTH = 65;\n    uint256 private constant OFFSET_R = 0;\n    uint256 private constant OFFSET_S = 32;\n    uint256 private constant OFFSET_V = 64;\n\n    /**\n     * @dev Calldata memory layout\n     * [000 .. 004) selector    bytes4  4 bytes\n     *      Optional: N function arguments\n     * [004 .. 036) arg1        bytes32 32 bytes\n     *      ..\n     * [AAA .. END) argN        bytes32 32 bytes\n     */\n    uint256 internal constant SELECTOR_LENGTH = 4;\n    uint256 private constant OFFSET_SELECTOR = 0;\n    uint256 private constant OFFSET_ARGUMENTS = SELECTOR_LENGTH;\n\n    // ═════════════════════════════════════════════════ SIGNATURE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the signature payload from the given values.\n     * @dev Using ByteString.formatSignature({r: r, s: s, v: v}) will make sure\n     * that params are given in the right order.\n     */\n    function formatSignature(bytes32 r, bytes32 s, uint8 v) internal pure returns (bytes memory) {\n        return abi.encodePacked(r, s, v);\n    }\n\n    /**\n     * @notice Returns a Signature view over for the given payload.\n     * @dev Will revert if the payload is not a signature.\n     */\n    function castToSignature(bytes memory payload) internal pure returns (Signature) {\n        return castToSignature(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Signature view.\n     * @dev Will revert if the memory view is not over a signature.\n     */\n    function castToSignature(MemView memView) internal pure returns (Signature) {\n        if (!isSignature(memView)) revert UnformattedSignature();\n        return Signature.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a signature\n     */\n    function isSignature(MemView memView) internal pure returns (bool) {\n        return memView.len() == SIGNATURE_LENGTH;\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Signature signature) internal pure returns (MemView) {\n        return MemView.wrap(Signature.unwrap(signature));\n    }\n\n    // ═════════════════════════════════════════════ SIGNATURE SLICING ═════════════════════════════════════════════════\n\n    /// @notice Unpacks signature payload into (r, s, v) parameters.\n    /// @dev Make sure to verify signature length with isSignature() beforehand.\n    function toRSV(Signature signature) internal pure returns (bytes32 r, bytes32 s, uint8 v) {\n        // Get the underlying memory view\n        MemView memView = unwrap(signature);\n        r = memView.index({index_: OFFSET_R, bytes_: 32});\n        s = memView.index({index_: OFFSET_S, bytes_: 32});\n        // Can be safely casted to uint8, since we index a single byte\n        v = uint8(memView.indexUint({index_: OFFSET_V, bytes_: 1}));\n    }\n\n    // ═════════════════════════════════════════════════ CALLDATA ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the calldata with the modified arguments:\n     * the existing arguments are prepended with the arguments from the prefix.\n     * @dev Given:\n     *  - `calldata = abi.encodeWithSelector(foo.selector, d, e);`\n     *  - `prefix = abi.encode(a, b, c);`\n     *  - `a`, `b`, `c` are arguments of static type (i.e. not dynamically sized ones)\n     *      Then:\n     *  - Function will return abi.encodeWithSelector(foo.selector, a, c, c, d, e)\n     *  - Returned calldata will trigger `foo(a, b, c, d, e)` when used for a contract call.\n     * Note: for clarification as to what types are considered static, see\n     * https://docs.soliditylang.org/en/latest/abi-spec.html#formal-specification-of-the-encoding\n     * @param callData  Calldata that needs to be modified\n     * @param prefix    ABI-encoded arguments to use as the first arguments in the new calldata\n     * @return Modified calldata having prefix as the first arguments.\n     */\n    function addPrefix(CallData callData, bytes memory prefix) internal view returns (bytes memory) {\n        // Prefix should occupy a whole amount of words in memory\n        if (!_fullWords(prefix.length)) revert UnformattedCallDataPrefix();\n        MemView[] memory views = new MemView[](3);\n        // Use payload's function selector\n        views[0] = abi.encodePacked(callData.callSelector()).ref();\n        // Use prefix as the first arguments\n        views[1] = prefix.ref();\n        // Use payload's remaining arguments\n        views[2] = callData.arguments();\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a CallData view over for the given payload.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(bytes memory payload) internal pure returns (CallData) {\n        return castToCallData(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a CallData view.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(MemView memView) internal pure returns (CallData) {\n        if (!isCallData(memView)) revert UnformattedCallData();\n        return CallData.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a valid calldata, i.e.\n     * a function selector, followed by arbitrary amount of arguments.\n     */\n    function isCallData(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Calldata should at least have a function selector\n        if (length \u003c SELECTOR_LENGTH) return false;\n        // The remainder of the calldata should be exactly N memory words (N \u003e= 0)\n        return _fullWords(length - SELECTOR_LENGTH);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(CallData callData) internal pure returns (MemView) {\n        return MemView.wrap(CallData.unwrap(callData));\n    }\n\n    /// @notice Returns callData's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(CallData callData) internal pure returns (bytes32) {\n        return callData.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ CALLDATA SLICING ══════════════════════════════════════════════════\n\n    /**\n     * @notice Returns amount of memory words (32 byte chunks) the function arguments\n     * occupy in the calldata.\n     * @dev This might differ from amount of arguments supplied, if any of the arguments\n     * occupies more than one memory slot. It is true, however, that argument part of the payload\n     * occupies exactly N words, even for dynamic types like `bytes`\n     */\n    function argumentWords(CallData callData) internal pure returns (uint256) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        // Equivalent of (length - SELECTOR_LENGTH) / 32\n        return (memView.len() - SELECTOR_LENGTH) \u003e\u003e 5;\n    }\n\n    /// @notice Returns selector for the provided calldata.\n    function callSelector(CallData callData) internal pure returns (bytes4) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return bytes4(memView.index({index_: OFFSET_SELECTOR, bytes_: SELECTOR_LENGTH}));\n    }\n\n    /// @notice Returns abi encoded arguments for the provided calldata.\n    function arguments(CallData callData) internal pure returns (MemView) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return memView.sliceFrom({index_: OFFSET_ARGUMENTS});\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if length is full amount of memory words (32 bytes).\n    function _fullWords(uint256 length) internal pure returns (bool) {\n        // The equivalent of length % 32 == 0\n        return length \u0026 31 == 0;\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n    function __Context_init() internal onlyInitializing {\n    }\n\n    function __Context_init_unchained() internal onlyInitializing {\n    }\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[50] private __gap;\n}\n\n// contracts/libs/merkle/MerkleTree.sol\n\n/// `BaseTree` is a struct representing incremental merkle tree.\n/// - Contains only the current branch.\n/// - The number of inserted leaves is stored externally, and is later supplied for tree operations.\n/// - Has a fixed height of `ORIGIN_TREE_HEIGHT`.\n/// - Can store up to `2 ** ORIGIN_TREE_HEIGHT - 1` leaves.\n/// \u003e Note: the hash function for the tree `H(x, y)` is defined as:\n/// \u003e - `H(0,0) = 0`\n/// \u003e - `H(x,y) = keccak256(x, y), when (x != 0 || y != 0)`\n/// ## Invariant for leafs\n/// - The leftmost empty leaf has `index == count`, where `count` is the amount of the inserted leafs so far.\n/// - Value for any empty leaf or node is bytes32(0).\n/// ## Invariant for current branch\n/// `branch[i]` is always the value of a node on the i-th level.\n/// Levels are numbered from leafs to root: `0 .. ORIGIN_TREE_HEIGHT`.\n/// `branch[i]` stores the value for the node, such that:\n//  - The node is a \"left child\" (e.g. has an even index).\n/// - The node must have two non-empty children.\n/// - Out of all level's \"left child\" nodes with \"non-empty children\",\n/// the one with the biggest index (the rightmost one) is stored as `branch[i]`.\n/// \u003e __`branch` could be used to form a proof of inclusion for the first empty leaf (`index == count`).__\n/// _Here is how:_\n/// - Let's walk along the path from the \"first empty leaf\" to the root.\n/// - i-th bit of the \"first empty leaf\" index (which is equal to `count`) determines if the path's node\n/// for this i-th level is a \"left child\" or a \"right child\".\n/// - i-th bit in `count` is 0 → we are the left child on this level → sibling is the right child\n/// that does not exist yet → `proof[i] = bytes32(0)`.\n/// - i-th bit in `count` is 1 → we are the right child on this level → sibling is the left child\n/// sibling is the rightmost \"left child\" node on the level → `proof[i] = branch[i]`.\n/// \u003e Therefore `proof[i] = (count \u0026 (1 \u003c\u003c i)) == 0 ? bytes32(0) : branch[i])`\nstruct BaseTree {\n    bytes32[ORIGIN_TREE_HEIGHT] branch;\n}\n\nusing MerkleTree for BaseTree global;\n\n/// `HistoricalTree` is an incremental merkle tree keeping track of its historical merkle roots.\n/// \u003e - `roots[N]` is the root of the tree after `N` leafs were inserted\n/// \u003e - `roots[0] == bytes32(0)`\n/// @param tree     Incremental merkle tree\n/// @param roots    Historical merkle roots of the tree\nstruct HistoricalTree {\n    BaseTree tree;\n    bytes32[] roots;\n}\n\nusing MerkleTree for HistoricalTree global;\n\n/// `DynamicTree` is a struct representing a Merkle Tree with `2**AGENT_TREE_HEIGHT` leaves.\n/// - A single operation is available: update value for leaf with an arbitrary index (which might be a non-empty leaf).\n/// - This is done by requesting the proof of inclusion for the old value, which is used to both\n/// verify the old value, and calculate the new root.\n/// \u003e Based on Original idea from [ER forum post](https://ethresear.ch/t/efficient-on-chain-dynamic-merkle-tree/11054).\nstruct DynamicTree {\n    bytes32 root;\n}\n\nusing MerkleTree for DynamicTree global;\n\n/// MerkleTree is work based on Nomad's Merkle.sol, which is used under MIT OR Apache-2.0\n/// [link](https://github.com/nomad-xyz/monorepo/blob/main/packages/contracts-core/contracts/libs/Merkle.sol).\n/// With the following changes:\n/// - Adapted for Solidity 0.8.x.\n/// - Amount of tree leaves stored externally.\n/// - Added thorough documentation.\n/// - `H(0,0) = 0` optimization from [ER forum post](https://ethresear.ch/t/optimizing-sparse-merkle-trees/3751/6).\n/// \u003e Nomad's Merkle.sol is work based on eth2 deposit contract, which is used under CC0-1.0\n///[link](https://github.com/ethereum/deposit_contract/blob/dev/deposit_contract/contracts/validator_registration.v.py).\n/// With the following changes:\n/// \u003e - Implemented in Solidity 0.7.6 (eth2 deposit contract implemented in Vyper).\n/// \u003e - `H() = keccak256()` is used as the hashing function instead of `sha256()`.\nlibrary MerkleTree {\n    /// @dev For root calculation we need at least one empty leaf, thus the minus one in the formula.\n    uint256 internal constant MAX_LEAVES = 2 ** ORIGIN_TREE_HEIGHT - 1;\n\n    // ═════════════════════════════════════════════════ BASE TREE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Inserts `node` into merkle tree\n     * @dev Reverts if tree is full\n     * @param newCount  Amount of inserted leaves in the tree after the insertion (i.e. current + 1)\n     * @param node      Element to insert into tree\n     */\n    function insertBase(BaseTree storage tree, uint256 newCount, bytes32 node) internal {\n        if (newCount \u003e MAX_LEAVES) revert MerkleTreeFull();\n        // We go up the tree following the branch from the empty leaf AFTER the just inserted one.\n        // We stop when we find the first \"right child\" node.\n        // Its sibling is now the rightmost \"left child\" node that has two non-empty children.\n        // Therefore we need to update `tree.branch` value on this level.\n        // One could see that `tree.branch` value on lower and higher levels remain unchanged.\n\n        // Loop invariant: `node` is the current level's value for the branch from JUST INSERTED leaf\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            if ((newCount \u0026 1) == 1) {\n                // Found the first \"right child\" node on the branch from EMPTY leaf\n                // `node` is the value for node on branch from JUST INSERTED leaf\n                // Which in this case is the \"left child\".\n                // We update tree.branch and exit\n                tree.branch[i] = node;\n                return;\n            }\n            // On the branch from EMPTY leaf this is still a \"left child\".\n            // Meaning on branch from JUST INSERTED leaf, `node` is a right child.\n            // We compute value for `node` parent using `tree.branch` invariant:\n            // This is the rightmost \"left child\" node, which would be sibling of `node`.\n            node = MerkleMath.getParent(tree.branch[i], node);\n            // Get the parent index, and go to the next tree level\n            newCount \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n        // As the loop should always end prematurely with the `return` statement,\n        // this code should be unreachable. We assert `false` just to be safe.\n        assert(false);\n    }\n\n    /**\n     * @notice Calculates and returns current root of the merkle tree.\n     * @param count     Current amount of inserted leaves in the tree\n     * @return current  Calculated root of `tree`\n     */\n    function rootBase(BaseTree storage tree, uint256 count) internal view returns (bytes32 current) {\n        // To calculate the root we follow the branch of first EMPTY leaf (index == count)\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            // Check if we are the left or the right child on the current level\n            if ((count \u0026 1) == 1) {\n                // We are the right child. Our sibling is the \"rightmost\" \"left-child\" node\n                // that has two non-empty children → sibling is `tree.branch[i]`\n                current = MerkleMath.getParent(tree.branch[i], current);\n            } else {\n                // We are the left child. Our sibling does not exist yet → sibling is EMPTY\n                current = MerkleMath.getParent(current, bytes32(0));\n            }\n            // Get the parent index, and go to the next tree level\n            count \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    // ══════════════════════════════════════════════ HISTORICAL TREE ══════════════════════════════════════════════════\n\n    /// @notice Initializes the historical roots for the tree by inserting an empty root.\n    // solhint-disable-next-line ordering\n    function initializeRoots(HistoricalTree storage tree) internal returns (bytes32 savedRoot) {\n        // This should only be called once, when the contract is initialized\n        assert(tree.roots.length == 0);\n        // Save root for empty merkle tree: bytes32(0)\n        tree.roots.push(savedRoot);\n    }\n\n    /// @notice Inserts a new leaf into the merkle tree.\n    /// @dev Reverts if tree is full.\n    /// @param node         Element to insert into tree\n    /// @return newRoot     Merkle root after the leaf was inserted\n    function insert(HistoricalTree storage tree, bytes32 node) internal returns (bytes32 newRoot) {\n        // Tree count after the new leaf will be inserted (we store roots[0] as root of empty tree)\n        uint256 newCount = tree.roots.length;\n        tree.tree.insertBase(newCount, node);\n        // Save the new root\n        newRoot = tree.tree.rootBase(newCount);\n        tree.roots.push(newRoot);\n    }\n\n    /// @notice Returns the historical root of the merkle tree.\n    /// @dev Reverts if not enough leafs have been inserted.\n    /// @param count            Amount of leafs in the tree at some point of time\n    /// @return historicalRoot  Merkle root after `count` leafs were inserted\n    function root(HistoricalTree storage tree, uint256 count) internal view returns (bytes32 historicalRoot) {\n        if (count \u003e= tree.roots.length) revert NotEnoughLeafs();\n        return tree.roots[count];\n    }\n\n    // ═══════════════════════════════════════════════ DYNAMIC TREE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Updates the value for the leaf with the given index in the Dynamic Merkle Tree.\n     * @dev Will revert if incorrect proof of inclusion for old value is supplied.\n     * @param tree          Dynamic merkle tree\n     * @param index         Index of the leaf to update\n     * @param oldValue      Previous value of the leaf\n     * @param branch        Proof of inclusion of previous value into the tree\n     * @param newValue      New leaf value to assign\n     * @return newRoot      New value for the Merkle Root after the leaf is updated\n     */\n    function update(\n        DynamicTree storage tree,\n        uint256 index,\n        bytes32 oldValue,\n        bytes32[] memory branch,\n        bytes32 newValue\n    ) internal returns (bytes32 newRoot) {\n        // Check that the old value + proof result in a correct root\n        if (MerkleMath.proofRoot(index, oldValue, branch, AGENT_TREE_HEIGHT) != tree.root) {\n            revert LeafNotProven();\n        }\n        // New root is new value + the same proof (values for sibling nodes are not updated)\n        newRoot = MerkleMath.proofRoot(index, newValue, branch, AGENT_TREE_HEIGHT);\n        // Write the new root\n        tree.root = newRoot;\n    }\n}\n\n// contracts/libs/stack/Tips.sol\n\n/// Tips is encoded data with \"tips paid for sending a base message\".\n/// Note: even though uint256 is also an underlying type for MemView, Tips is stored ON STACK.\ntype Tips is uint256;\n\nusing TipsLib for Tips global;\n\n/// # Tips\n/// Library for formatting _the tips part_ of _the base messages_.\n///\n/// ## How the tips are awarded\n/// Tips are paid for sending a base message, and are split across all the agents that\n/// made the message execution on destination chain possible.\n/// ### Summit tips\n/// Split between:\n///     - Guard posting a snapshot with state ST_G for the origin chain.\n///     - Notary posting a snapshot SN_N using ST_G. This creates attestation A.\n///     - Notary posting a message receipt after it is executed on destination chain.\n/// ### Attestation tips\n/// Paid to:\n///     - Notary posting attestation A to destination chain.\n/// ### Execution tips\n/// Paid to:\n///     - First executor performing a valid execution attempt (correct proofs, optimistic period over),\n///      using attestation A to prove message inclusion on origin chain, whether the recipient reverted or not.\n/// ### Delivery tips.\n/// Paid to:\n///     - Executor who successfully executed the message on destination chain.\n///\n/// ## Tips encoding\n/// - Tips occupy a single storage word, and thus are stored on stack instead of being stored in memory.\n/// - The actual tip values should be determined by multiplying stored values by divided by TIPS_MULTIPLIER=2**32.\n/// - Tips are packed into a single word of storage, while allowing real values up to ~8*10**28 for every tip category.\n/// \u003e The only downside is that the \"real tip values\" are now multiplies of ~4*10**9, which should be fine even for\n/// the chains with the most expensive gas currency.\n/// # Tips stack layout (from highest bits to lowest)\n///\n/// | Position   | Field          | Type   | Bytes | Description                                                |\n/// | ---------- | -------------- | ------ | ----- | ---------------------------------------------------------- |\n/// | (032..024] | summitTip      | uint64 | 8     | Tip for agents interacting with Summit contract            |\n/// | (024..016] | attestationTip | uint64 | 8     | Tip for Notary posting attestation to Destination contract |\n/// | (016..008] | executionTip   | uint64 | 8     | Tip for valid execution attempt on destination chain       |\n/// | (008..000] | deliveryTip    | uint64 | 8     | Tip for successful message delivery on destination chain   |\n\nlibrary TipsLib {\n    using SafeCast for uint256;\n\n    /// @dev Amount of bits to shift to summitTip field\n    uint256 private constant SHIFT_SUMMIT_TIP = 24 * 8;\n    /// @dev Amount of bits to shift to attestationTip field\n    uint256 private constant SHIFT_ATTESTATION_TIP = 16 * 8;\n    /// @dev Amount of bits to shift to executionTip field\n    uint256 private constant SHIFT_EXECUTION_TIP = 8 * 8;\n\n    // ═══════════════════════════════════════════════════ TIPS ════════════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips with the given fields\n    /// @param summitTip_        Tip for agents interacting with Summit contract, divided by TIPS_MULTIPLIER\n    /// @param attestationTip_   Tip for Notary posting attestation to Destination contract, divided by TIPS_MULTIPLIER\n    /// @param executionTip_     Tip for valid execution attempt on destination chain, divided by TIPS_MULTIPLIER\n    /// @param deliveryTip_      Tip for successful message delivery on destination chain, divided by TIPS_MULTIPLIER\n    function encodeTips(uint64 summitTip_, uint64 attestationTip_, uint64 executionTip_, uint64 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // forgefmt: disable-next-item\n        return Tips.wrap(\n            uint256(summitTip_) \u003c\u003c SHIFT_SUMMIT_TIP |\n            uint256(attestationTip_) \u003c\u003c SHIFT_ATTESTATION_TIP |\n            uint256(executionTip_) \u003c\u003c SHIFT_EXECUTION_TIP |\n            uint256(deliveryTip_)\n        );\n    }\n\n    /// @notice Convenience function to encode tips with uint256 values.\n    function encodeTips256(uint256 summitTip_, uint256 attestationTip_, uint256 executionTip_, uint256 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // In practice, the tips amounts are not supposed to be higher than 2**96, and with 32 bits of granularity\n        // using uint64 is enough to store the values. However, we still check for overflow just in case.\n        // TODO: consider using Number type to store the tips values.\n        return encodeTips({\n            summitTip_: (summitTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            attestationTip_: (attestationTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            executionTip_: (executionTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            deliveryTip_: (deliveryTip_ \u003e\u003e TIPS_GRANULARITY).toUint64()\n        });\n    }\n\n    /// @notice Wraps the padded encoded tips into a Tips-typed value.\n    /// @dev There is no actual padding here, as the underlying type is already uint256,\n    /// but we include this function for consistency and to be future-proof, if tips will eventually use anything\n    /// smaller than uint256.\n    function wrapPadded(uint256 paddedTips) internal pure returns (Tips) {\n        return Tips.wrap(paddedTips);\n    }\n\n    /**\n     * @notice Returns a formatted Tips payload specifying empty tips.\n     * @return Formatted tips\n     */\n    function emptyTips() internal pure returns (Tips) {\n        return Tips.wrap(0);\n    }\n\n    /// @notice Returns tips's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Tips tips) internal pure returns (bytes32 hashedTips) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store tips in scratch space\n            mstore(0, tips)\n            // Compute hash of tips padded to 32 bytes\n            hashedTips := keccak256(0, 32)\n        }\n    }\n\n    // ═══════════════════════════════════════════════ TIPS SLICING ════════════════════════════════════════════════════\n\n    /// @notice Returns summitTip field\n    function summitTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_SUMMIT_TIP);\n    }\n\n    /// @notice Returns attestationTip field\n    function attestationTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_ATTESTATION_TIP);\n    }\n\n    /// @notice Returns executionTip field\n    function executionTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_EXECUTION_TIP);\n    }\n\n    /// @notice Returns deliveryTip field\n    function deliveryTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips));\n    }\n\n    // ════════════════════════════════════════════════ TIPS VALUE ═════════════════════════════════════════════════════\n\n    /// @notice Returns total value of the tips payload.\n    /// This is the sum of the encoded values, scaled up by TIPS_MULTIPLIER\n    function value(Tips tips) internal pure returns (uint256 value_) {\n        value_ = uint256(tips.summitTip()) + tips.attestationTip() + tips.executionTip() + tips.deliveryTip();\n        value_ \u003c\u003c= TIPS_GRANULARITY;\n    }\n\n    /// @notice Increases the delivery tip to match the new value.\n    function matchValue(Tips tips, uint256 newValue) internal pure returns (Tips newTips) {\n        uint256 oldValue = tips.value();\n        if (newValue \u003c oldValue) revert TipsValueTooLow();\n        // We want to increase the delivery tip, while keeping the other tips the same\n        unchecked {\n            uint256 delta = (newValue - oldValue) \u003e\u003e TIPS_GRANULARITY;\n            // `delta` fits into uint224, as TIPS_GRANULARITY is 32, so this never overflows uint256.\n            // In practice, this will never overflow uint64 as well, but we still check it just in case.\n            if (delta + tips.deliveryTip() \u003e type(uint64).max) revert TipsOverflow();\n            // Delivery tips occupy lowest 8 bytes, so we can just add delta to the tips value\n            // to effectively increase the delivery tip (knowing that delta fits into uint64).\n            newTips = Tips.wrap(Tips.unwrap(tips) + delta);\n        }\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    function __Ownable_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable_init_unchained() internal onlyInitializing {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n    function __Ownable2Step_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable2Step_init_unchained() internal onlyInitializing {\n    }\n    address private _pendingOwner;\n\n    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Returns the address of the pending owner.\n     */\n    function pendingOwner() public view virtual returns (address) {\n        return _pendingOwner;\n    }\n\n    /**\n     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual override onlyOwner {\n        _pendingOwner = newOwner;\n        emit OwnershipTransferStarted(owner(), newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual override {\n        delete _pendingOwner;\n        super._transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev The new owner accepts the ownership transfer.\n     */\n    function acceptOwnership() public virtual {\n        address sender = _msgSender();\n        require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n        _transferOwnership(sender);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// contracts/libs/memory/State.sol\n\n/// State is a memory view over a formatted state payload.\ntype State is uint256;\n\nusing StateLib for State global;\n\n/// # State\n/// State structure represents the state of Origin contract at some point of time.\n/// - State is structured in a way to track the updates of the Origin Merkle Tree.\n/// - State includes root of the Origin Merkle Tree, origin domain and some additional metadata.\n/// ## Origin Merkle Tree\n/// Hash of every sent message is inserted in the Origin Merkle Tree, which changes\n/// the value of Origin Merkle Root (which is the root for the mentioned tree).\n/// - Origin has a single Merkle Tree for all messages, regardless of their destination domain.\n/// - This leads to Origin state being updated if and only if a message was sent in a block.\n/// - Origin contract is a \"source of truth\" for states: a state is considered \"valid\" in its Origin,\n/// if it matches the state of the Origin contract after the N-th (nonce) message was sent.\n///\n/// # Memory layout of State fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                    |\n/// | ---------- | ----------- | ------- | ----- | ------------------------------ |\n/// | [000..032) | root        | bytes32 | 32    | Root of the Origin Merkle Tree |\n/// | [032..036) | origin      | uint32  | 4     | Domain where Origin is located |\n/// | [036..040) | nonce       | uint32  | 4     | Amount of sent messages        |\n/// | [040..045) | blockNumber | uint40  | 5     | Block of last sent message     |\n/// | [045..050) | timestamp   | uint40  | 5     | Time of last sent message      |\n/// | [050..062) | gasData     | uint96  | 12    | Gas data for the chain         |\n///\n/// @dev State could be used to form a Snapshot to be signed by a Guard or a Notary.\nlibrary StateLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_ROOT = 0;\n    uint256 private constant OFFSET_ORIGIN = 32;\n    uint256 private constant OFFSET_NONCE = 36;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 40;\n    uint256 private constant OFFSET_TIMESTAMP = 45;\n    uint256 private constant OFFSET_GAS_DATA = 50;\n\n    // ═══════════════════════════════════════════════════ STATE ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted State payload with provided fields\n     * @param root_         New merkle root\n     * @param origin_       Domain of Origin's chain\n     * @param nonce_        Nonce of the merkle root\n     * @param blockNumber_  Block number when root was saved in Origin\n     * @param timestamp_    Block timestamp when root was saved in Origin\n     * @param gasData_      Gas data for the chain\n     * @return Formatted state\n     */\n    function formatState(\n        bytes32 root_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_,\n        GasData gasData_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(root_, origin_, nonce_, blockNumber_, timestamp_, gasData_);\n    }\n\n    /**\n     * @notice Returns a State view over the given payload.\n     * @dev Will revert if the payload is not a state.\n     */\n    function castToState(bytes memory payload) internal pure returns (State) {\n        return castToState(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a State view.\n     * @dev Will revert if the memory view is not over a state.\n     */\n    function castToState(MemView memView) internal pure returns (State) {\n        if (!isState(memView)) revert UnformattedState();\n        return State.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted State.\n    function isState(MemView memView) internal pure returns (bool) {\n        return memView.len() == STATE_LENGTH;\n    }\n\n    /// @notice Returns the hash of a State, that could be later signed by a Guard to signal\n    /// that the state is invalid.\n    function hashInvalid(State state) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(stateInvalidSalt, keccak(state))\n        return state.unwrap().keccakSalted(STATE_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(State state) internal pure returns (MemView) {\n        return MemView.wrap(State.unwrap(state));\n    }\n\n    /// @notice Compares two State structures.\n    function equals(State a, State b) internal pure returns (bool) {\n        // Length of a State payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═══════════════════════════════════════════════ STATE HASHING ═══════════════════════════════════════════════════\n\n    /// @notice Returns the hash of the State.\n    /// @dev We are using the Merkle Root of a tree with two leafs (see below) as state hash.\n    function leaf(State state) internal pure returns (bytes32) {\n        (bytes32 leftLeaf_, bytes32 rightLeaf_) = state.subLeafs();\n        // Final hash is the parent of these leafs\n        return keccak256(bytes.concat(leftLeaf_, rightLeaf_));\n    }\n\n    /// @notice Returns \"sub-leafs\" of the State. Hash of these \"sub leafs\" is going to be used\n    /// as a \"state leaf\" in the \"Snapshot Merkle Tree\".\n    /// This enables proving that leftLeaf = (root, origin) was a part of the \"Snapshot Merkle Tree\",\n    /// by combining `rightLeaf` with the remainder of the \"Snapshot Merkle Proof\".\n    function subLeafs(State state) internal pure returns (bytes32 leftLeaf_, bytes32 rightLeaf_) {\n        MemView memView = state.unwrap();\n        // Left leaf is (root, origin)\n        leftLeaf_ = memView.prefix({len_: OFFSET_NONCE}).keccak();\n        // Right leaf is (metadata), or (nonce, blockNumber, timestamp)\n        rightLeaf_ = memView.sliceFrom({index_: OFFSET_NONCE}).keccak();\n    }\n\n    /// @notice Returns the left \"sub-leaf\" of the State.\n    function leftLeaf(bytes32 root_, uint32 origin_) internal pure returns (bytes32) {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(root_, origin_));\n    }\n\n    /// @notice Returns the right \"sub-leaf\" of the State.\n    function rightLeaf(uint32 nonce_, uint40 blockNumber_, uint40 timestamp_, GasData gasData_)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(nonce_, blockNumber_, timestamp_, gasData_));\n    }\n\n    // ═══════════════════════════════════════════════ STATE SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns a historical Merkle root from the Origin contract.\n    function root(State state) internal pure returns (bytes32) {\n        return state.unwrap().index({index_: OFFSET_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns domain of chain where the Origin contract is deployed.\n    function origin(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns nonce of Origin contract at the time, when `root` was the Merkle root.\n    function nonce(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when `root` was saved in Origin.\n    function blockNumber(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when `root` was saved in Origin.\n    /// @dev This is the timestamp according to the origin chain.\n    function timestamp(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n\n    /// @notice Returns gas data for the chain.\n    function gasData(State state) internal pure returns (GasData) {\n        return GasDataLib.wrapGasData(state.unwrap().indexUint({index_: OFFSET_GAS_DATA, bytes_: GAS_DATA_LENGTH}));\n    }\n}\n\n// contracts/libs/memory/BaseMessage.sol\n\n/// BaseMessage is a memory view over the base message supported by Origin-Destination\ntype BaseMessage is uint256;\n\nusing BaseMessageLib for BaseMessage global;\n\n/// BaseMessage structure represents a base message sent via the Origin-Destination contracts.\n/// - It only contains data relevant to the base message, the rest of data is encoded in the message header.\n/// - `sender` and `recipient` for EVM chains are EVM addresses casted to bytes32, while preserving left-alignment.\n/// - `tips` and `request` parameters are specified by a message sender\n/// \u003e Origin will calculate minimum tips for given request and content length, and will reject messages with tips\n/// lower than that.\n///\n/// # Memory layout of BaseMessage fields\n///\n/// | Position   | Field     | Type    | Bytes | Description                            |\n/// | ---------- | --------- | ------- | ----- | -------------------------------------- |\n/// | [000..032) | tips      | uint256 | 32    | Encoded tips paid on origin chain      |\n/// | [032..064) | sender    | bytes32 | 32    | Sender address on origin chain         |\n/// | [064..096) | recipient | bytes32 | 32    | Recipient address on destination chain |\n/// | [096..116) | request   | uint160 | 20    | Encoded request for message execution  |\n/// | [104..AAA) | content   | bytes   | ??    | Content to be passed to recipient      |\nlibrary BaseMessageLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_TIPS = 0;\n    uint256 private constant OFFSET_SENDER = 32;\n    uint256 private constant OFFSET_RECIPIENT = 64;\n    uint256 private constant OFFSET_REQUEST = OFFSET_RECIPIENT + TIPS_LENGTH;\n    uint256 private constant OFFSET_CONTENT = OFFSET_REQUEST + REQUEST_LENGTH;\n\n    // ═══════════════════════════════════════════════ BASE MESSAGE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted BaseMessage payload with provided fields.\n     * @param tips_         Encoded tips information\n     * @param sender_       Sender address on origin chain\n     * @param recipient_    Recipient address on destination chain\n     * @param request_      Encoded request for message execution\n     * @param content_      Raw content to be passed to recipient on destination chain\n     * @return Formatted base message\n     */\n    function formatBaseMessage(Tips tips_, bytes32 sender_, bytes32 recipient_, Request request_, bytes memory content_)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return abi.encodePacked(tips_, sender_, recipient_, request_, content_);\n    }\n\n    /**\n     * @notice Returns a BaseMessage view over the given payload.\n     * @dev Will revert if the payload is not a base message.\n     */\n    function castToBaseMessage(bytes memory payload) internal pure returns (BaseMessage) {\n        return castToBaseMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a BaseMessage view.\n     * @dev Will revert if the memory view is not over a base message payload.\n     */\n    function castToBaseMessage(MemView memView) internal pure returns (BaseMessage) {\n        if (!isBaseMessage(memView)) revert UnformattedBaseMessage();\n        return BaseMessage.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted BaseMessage.\n    function isBaseMessage(MemView memView) internal pure returns (bool) {\n        // Check if sender, recipient, tips fields exist\n        return (memView.len() \u003e= OFFSET_CONTENT);\n        // Content could be empty, so we don't check that\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(BaseMessage baseMessage) internal pure returns (MemView) {\n        return MemView.wrap(BaseMessage.unwrap(baseMessage));\n    }\n\n    /// @notice Returns baseMessage's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        // We hash \"tips\" and \"everything but tips\" to make tips proofs easier to verify\n        return MerkleMath.getParent(baseMessage.tips().leaf(), baseMessage.bodyLeaf());\n    }\n\n    /// @notice Returns hash for the \"everything but tips\" part of the base message.\n    function bodyLeaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_SENDER}).keccak();\n    }\n\n    // ═══════════════════════════════════════════ BASE MESSAGE SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips paid on origin chain.\n    function tips(BaseMessage baseMessage) internal pure returns (Tips) {\n        return TipsLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_TIPS, bytes_: TIPS_LENGTH})));\n    }\n\n    /// @notice Returns sender address on origin chain.\n    function sender(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_SENDER, bytes_: 32});\n    }\n\n    /// @notice Returns recipient address on destination chain.\n    function recipient(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_RECIPIENT, bytes_: 32});\n    }\n\n    /// @notice Returns an encoded request for message execution on destination chain.\n    function request(BaseMessage baseMessage) internal pure returns (Request) {\n        return RequestLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_REQUEST, bytes_: REQUEST_LENGTH})));\n    }\n\n    /// @notice Returns an untyped memory view over the content to be passed to recipient.\n    function content(BaseMessage baseMessage) internal pure returns (MemView) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_CONTENT});\n    }\n}\n\n// contracts/base/MessagingBase.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for all messaging contracts.\n * - Provides context on the local chain's domain.\n * - Provides ownership functionality.\n * - Will be providing pausing functionality when it is implemented.\n */\nabstract contract MessagingBase is MultiCallable, Versioned, Ownable2StepUpgradeable {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @notice Domain of the local chain, set once upon contract creation\n    uint32 public immutable localDomain;\n    // @notice Domain of the Synapse chain, set once upon contract creation\n    uint32 public immutable synapseDomain;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev gap for upgrade safety\n    uint256[50] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    constructor(string memory version_, uint32 synapseDomain_) Versioned(version_) {\n        localDomain = ChainContext.chainId();\n        synapseDomain = synapseDomain_;\n    }\n\n    // TODO: Implement pausing\n\n    /**\n     * @dev Should be impossible to renounce ownership;\n     * we override OpenZeppelin OwnableUpgradeable's\n     * implementation of renounceOwnership to make it a no-op\n     */\n    function renounceOwnership() public override onlyOwner {} //solhint-disable-line no-empty-blocks\n}\n\n// contracts/libs/memory/Message.sol\n\n/// Message is a memory over over a formatted message payload.\ntype Message is uint256;\n\nusing MessageLib for Message global;\n\n/// Library for formatting the various messages supported by Origin and Destination.\n///\n/// # Message memory layout\n///\n/// | Position   | Field  | Type    | Bytes | Description                                             |\n/// | ---------- | ------ | ------- | ----- | ------------------------------------------------------- |\n/// | [000..017) | header | uint136 | 17    | Encoded general routing information for the message     |\n/// | [017..AAA) | body   | bytes   | ??    | Formatted payload (according to flag) with message body |\nlibrary MessageLib {\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MemViewLib for bytes;\n    using HeaderLib for MemView;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_HEADER = 0;\n    uint256 private constant OFFSET_BODY = OFFSET_HEADER + HEADER_LENGTH;\n\n    // ══════════════════════════════════════════════════ MESSAGE ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns formatted message with provided fields.\n     * @param header_   Encoded general routing information for the message\n     * @param body_     Formatted payload (according to flag) with message body\n     * @return Formatted message\n     */\n    function formatMessage(Header header_, bytes memory body_) internal pure returns (bytes memory) {\n        return abi.encodePacked(header_, body_);\n    }\n\n    /**\n     * @notice Returns a Message view over for the given payload.\n     * @dev Will revert if the payload is not a message payload.\n     */\n    function castToMessage(bytes memory payload) internal pure returns (Message) {\n        return castToMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Message view.\n     * @dev Will revert if the memory view is not over a message payload.\n     */\n    function castToMessage(MemView memView) internal pure returns (Message) {\n        if (!isMessage(memView)) revert UnformattedMessage();\n        return Message.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Message.\n     */\n    function isMessage(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Check if headers exist in the payload\n        if (length \u003c OFFSET_BODY) return false;\n        // Check that Header is valid\n        uint256 paddedHeader = _header(memView);\n        if (!HeaderLib.isHeader(paddedHeader)) return false;\n        // Check that body is formatted according to the flag\n        // Only Base/Manager message flags exist\n        if (HeaderLib.wrapPadded(paddedHeader).flag() == MessageFlag.Base) {\n            // Check if body is a formatted base message\n            return _body(memView).isBaseMessage();\n        } else {\n            // Check if body is a formatted calldata for AgentManager call\n            return _body(memView).isCallData();\n        }\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Message message) internal pure returns (MemView) {\n        return MemView.wrap(Message.unwrap(message));\n    }\n\n    /// @notice Returns message's hash: a leaf to be inserted in the Merkle tree.\n    function leaf(Message message) internal pure returns (bytes32) {\n        // We hash header and body separately to make message proofs easier to verify\n        Header header_ = message.header();\n        // Only Base/Manager message flags exist\n        if (header_.flag() == MessageFlag.Base) {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToBaseMessage().leaf());\n        } else {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToCallData().leaf());\n        }\n    }\n\n    // ══════════════════════════════════════════════ MESSAGE SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns message's encoded header field.\n    function header(Message message) internal pure returns (Header) {\n        return HeaderLib.wrapPadded((message.unwrap().indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH})));\n    }\n\n    /// @notice Returns message's body field as an untyped memory view.\n    function body(Message message) internal pure returns (MemView) {\n        MemView memView = message.unwrap();\n        return _body(memView);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns message's padded header without checking that it is a valid header.\n    function _header(MemView memView) private pure returns (uint256) {\n        return memView.indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH});\n    }\n\n    /// @dev Returns an untyped memory view over the body field without checking\n    /// if the whole payload or the body are properly formatted.\n    function _body(MemView memView) private pure returns (MemView) {\n        return memView.sliceFrom({index_: OFFSET_BODY});\n    }\n}\n\n// contracts/base/AgentSecured.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for messaging contracts that are secured by the agent manager.\n * `AgentSecured` relies on `AgentManager` to provide the following functionality:\n * - Keep track of agents and their statuses.\n * - Pass agent-signed statements that were verified by the agent manager.\n * - These statements are considered valid indefinitely, unless the agent is disputed.\n * - Disputes are opened and resolved by the agent manager.\n * \u003e `AgentSecured` implementation should never use statements signed by agents that are disputed.\n */\nabstract contract AgentSecured is MessagingBase, IAgentSecured {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    address public immutable agentManager;\n\n    /// @inheritdoc IAgentSecured\n    address public immutable inbox;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    // (agent index =\u003e their dispute status: flag, openedAt, resolvedAt)\n    mapping(uint32 =\u003e DisputeStatus) internal _disputes;\n\n    /// @dev gap for upgrade safety\n    uint256[49] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    modifier onlyAgentManager() {\n        if (msg.sender != agentManager) revert CallerNotAgentManager();\n        _;\n    }\n\n    modifier onlyInbox() {\n        if (msg.sender != inbox) revert CallerNotInbox();\n        _;\n    }\n\n    constructor(string memory version_, uint32 synapseDomain_, address agentManager_, address inbox_)\n        MessagingBase(version_, synapseDomain_)\n    {\n        agentManager = agentManager_;\n        inbox = inbox_;\n    }\n\n    // ════════════════════════════════════════════ ONLY AGENT MANAGER ═════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external onlyAgentManager {\n        uint40 openedAt = ChainContext.blockTimestamp();\n        DisputeStatus memory status = DisputeStatus({flag: DisputeFlag.Pending, openedAt: openedAt, resolvedAt: 0});\n        _disputes[guardIndex] = status;\n        _disputes[notaryIndex] = status;\n    }\n\n    /// @inheritdoc IAgentSecured\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external onlyAgentManager {\n        // Update the dispute status of the slashed agent first.\n        uint40 resolvedAt = ChainContext.blockTimestamp();\n        _disputes[slashedIndex].flag = DisputeFlag.Slashed;\n        _disputes[slashedIndex].resolvedAt = resolvedAt;\n        // Mark the rival agent as not disputed, if there was an ongoing dispute.\n        if (rivalIndex != 0) {\n            _disputes[rivalIndex].flag = DisputeFlag.None;\n            _disputes[rivalIndex].resolvedAt = resolvedAt;\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function agentStatus(address agent) external view returns (AgentStatus memory) {\n        return _agentStatus(agent);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status) {\n        return _getAgent(index);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory) {\n        return _disputes[agentIndex];\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns status of the given agent: (flag, domain, index).\n    function _agentStatus(address agent) internal view returns (AgentStatus memory) {\n        return IAgentManager(agentManager).agentStatus(agent);\n    }\n\n    /// @dev Returns agent and their status for a given agent index. Returns zero values for non existing indexes.\n    function _getAgent(uint256 index) internal view returns (address agent, AgentStatus memory status) {\n        return IAgentManager(agentManager).getAgent(index);\n    }\n\n    /// @dev Checks if a Dispute exists for the given Notary. This function returns true, if\n    /// Notary is in ongoing Dispute, or if Dispute was resolved not in Notary's favor.\n    /// In both cases we can't trust Notary's data.\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeExists(uint32 notaryIndex) internal view returns (bool) {\n        return _disputes[notaryIndex].flag != DisputeFlag.None;\n    }\n\n    /// @dev Checks if a Notary recently won a Dispute and is still in the \"post-dispute\" timeout period.\n    /// In this period we still can't trust Notary's data, though we can optimistically assume that\n    /// that the data will be correct after the timeout (assuming no new Disputes are opened).\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeTimeout(uint32 notaryIndex) internal view returns (bool) {\n        DisputeStatus memory status = _disputes[notaryIndex];\n        // Exit early if Notary is in ongoing Dispute / slashed.\n        if (status.flag != DisputeFlag.None) return false;\n        // Check if Notary has been in any Dispute at all.\n        if (status.openedAt == 0) return false;\n        // Otherwise check if the Dispute timeout is still active.\n        return block.timestamp \u003c status.resolvedAt + DISPUTE_TIMEOUT_NOTARY;\n    }\n}\n\n// contracts/hubs/StateHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StateHub` is a parent contract for `Origin`. It is responsible for the following:\n/// - Keeping track of the historical Origin Merkle Tree containing all the message hashes.\n/// - Keeping track of the historical Origin States, as well as verifying their validity.\nabstract contract StateHub is AgentSecured, StateHubEvents, IStateHub {\n    using SafeCast for uint256;\n    using StateLib for bytes;\n\n    struct OriginState {\n        uint40 blockNumber;\n        uint40 timestamp;\n        GasData gasData;\n    }\n    // Bits left for tight packing: 80\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Historical Merkle Tree\n    /// Note: Takes two storage slots\n    HistoricalTree private _tree;\n\n    /// @dev All historical contract States\n    OriginState[] private _originStates;\n\n    /// @dev gap for upgrade safety\n    uint256[47] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IStateHub\n    function isValidState(bytes memory statePayload) external view returns (bool isValid) {\n        // This will revert if payload is not a formatted state\n        State state = statePayload.castToState();\n        return _isValidState(state);\n    }\n\n    /// @inheritdoc IStateHub\n    function statesAmount() external view returns (uint256) {\n        return _originStates.length;\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestLatestState() external view returns (bytes memory stateData) {\n        // This never underflows, assuming the contract was initialized\n        return suggestState(_nextNonce() - 1);\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestState(uint32 nonce) public view returns (bytes memory stateData) {\n        // This will revert if nonce is out of range\n        bytes32 root = _tree.root(nonce);\n        return _formatOriginState(_originStates[nonce], root, localDomain, nonce);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Initializes the saved states list by inserting a state for an empty Merkle Tree.\n    function _initializeStates() internal {\n        // This should only be called once, when the contract is initialized\n        // This will revert if _tree.roots is non-empty\n        bytes32 savedRoot = _tree.initializeRoots();\n        // Save root for empty merkle _tree with block number and timestamp of initialization\n        _saveState(savedRoot, _toOriginState());\n    }\n\n    /// @dev Inserts leaf into the Merkle Tree and saves the updated origin State.\n    function _insertAndSave(bytes32 leaf) internal {\n        bytes32 newRoot = _tree.insert(leaf);\n        _saveState(newRoot, _toOriginState());\n    }\n\n    /// @dev Saves an updated state of the Origin contract\n    function _saveState(bytes32 root, OriginState memory state) internal {\n        uint32 nonce = _nextNonce();\n        _originStates.push(state);\n        // Emit event with raw state data\n        emit StateSaved(_formatOriginState(state, root, localDomain, nonce));\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns nonce of the next sent message: the amount of saved States so far.\n    /// This always equals to \"total amount of sent messages\" plus 1.\n    function _nextNonce() internal view returns (uint32) {\n        // TODO: consider using more than 32 bits for origin nonces\n        return _originStates.length.toUint32();\n    }\n\n    /// @dev Checks if a state is valid, i.e. if it matches the historical one.\n    /// Reverts, if state refers to another Origin contract.\n    function _isValidState(State state) internal view returns (bool) {\n        // Check if state refers to this contract\n        if (state.origin() != localDomain) revert IncorrectOriginDomain();\n        // Check if nonce exists\n        uint32 nonce = state.nonce();\n        if (nonce \u003e= _originStates.length) return false;\n        // Check if state root matches the historical one\n        if (state.root() != _tree.root(nonce)) return false;\n        // Check if state metadata matches the historical one\n        return _areEqual(state, _originStates[nonce]);\n    }\n\n    // ═════════════════════════════════════════════ STRUCT FORMATTING ═════════════════════════════════════════════════\n\n    /// @dev Returns a formatted payload for a stored OriginState.\n    function _formatOriginState(OriginState memory originState, bytes32 root, uint32 origin, uint32 nonce)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return StateLib.formatState({\n            root_: root,\n            origin_: origin,\n            nonce_: nonce,\n            blockNumber_: originState.blockNumber,\n            timestamp_: originState.timestamp,\n            gasData_: originState.gasData\n        });\n    }\n\n    /// @dev Child contract should implement the logic for getting the current gas data from the gas oracle\n    /// to be saved as part of the Origin State.\n    // solhint-disable-next-line ordering\n    function _fetchGasData() internal view virtual returns (GasData);\n\n    /// @dev Returns a OriginState struct to save in the contract.\n    function _toOriginState() internal view returns (OriginState memory originState) {\n        originState.blockNumber = ChainContext.blockNumber();\n        originState.timestamp = ChainContext.blockTimestamp();\n        originState.gasData = _fetchGasData();\n    }\n\n    /// @dev Checks that a state and its Origin representation are equal.\n    function _areEqual(State state, OriginState memory originState) internal pure returns (bool) {\n        return state.blockNumber() == originState.blockNumber \u0026\u0026 state.timestamp() == originState.timestamp;\n    }\n}\n\n// contracts/Origin.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Origin` contract is used for sending messages to remote chains. It is done\n/// by inserting the message hashes into the Origin Merkle, which makes it possible to\n/// prove that message was sent using the Merkle proof against the Origin Merkle Root. This essentially\n/// compresses the list of messages into a single 32-byte value that needs to be stored on the destination chain.\n/// `Origin` is responsible for the following:\n/// - Formatting the sent message payloads, and inserting their hashes into the Origin Merkle Tree.\n/// - Keeping track of its own historical states (see parent contract `StateHub`).\n/// - Enforcing minimum tip values for sent base messages based on the provided execution requests.\n/// - Distributing the collected tips upon request from a local `AgentManager` contract.\ncontract Origin is StateHub, OriginEvents, InterfaceOrigin {\n    using MemViewLib for bytes;\n    using MessageLib for bytes;\n    using TipsLib for bytes;\n    using TypeCasts for address;\n\n    address public immutable gasOracle;\n\n    modifier onlyRemoteDestination(uint32 destination) {\n        if (destination == localDomain) revert IncorrectDestinationDomain();\n        _;\n    }\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_, address gasOracle_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {\n        gasOracle = gasOracle_;\n    }\n\n    /// @notice Initializes Origin contract:\n    /// - msg.sender is set as contract owner\n    /// - State of \"empty merkle tree\" is saved\n    function initialize() external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize \"states\": state of an \"empty merkle tree\" is saved\n        _initializeStates();\n    }\n\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable onlyRemoteDestination(destination) returns (uint32 messageNonce, bytes32 messageHash) {\n        // Check that content is not too large\n        if (content.length \u003e MAX_CONTENT_BYTES) revert ContentLengthTooBig();\n        // This will revert if msg.value is lower than value of minimum tips\n        Tips tips = _getMinimumTips(destination, paddedRequest, content.length).matchValue(msg.value);\n        Request request = RequestLib.wrapPadded(paddedRequest);\n        // Format the BaseMessage body\n        bytes memory body = BaseMessageLib.formatBaseMessage({\n            sender_: msg.sender.addressToBytes32(),\n            recipient_: recipient,\n            tips_: tips,\n            request_: request,\n            content_: content\n        });\n        // Send the message\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Base, body);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        onlyAgentManager\n        onlyRemoteDestination(destination)\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // AgentManager (checked via modifier) is responsible for constructing the calldata payload correctly.\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Manager, payload);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function withdrawTips(address recipient, uint256 amount) external onlyAgentManager {\n        if (address(this).balance \u003c amount) revert InsufficientEthBalance();\n        (bool success,) = recipient.call{value: amount}(\"\");\n        if (!success) revert EthTransferFailed();\n        emit TipWithdrawalCompleted(recipient, amount);\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue)\n    {\n        return _getMinimumTips(destination, paddedRequest, contentLength).value();\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Sends the given message to the specified destination. Message hash is inserted\n    /// into the Origin Merkle Tree, which will enable message execution on destination chain.\n    function _sendMessage(uint32 destination, uint32 optimisticPeriod, MessageFlag flag, bytes memory body)\n        internal\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // Format the message header\n        messageNonce = _nextNonce();\n        Header header = flag.encodeHeader({\n            origin_: localDomain,\n            nonce_: messageNonce,\n            destination_: destination,\n            optimisticPeriod_: optimisticPeriod\n        });\n        // Format the full message payload\n        bytes memory msgPayload = MessageLib.formatMessage(header, body);\n        // Insert new leaf into the Origin Merkle Tree and save the updated state\n        messageHash = msgPayload.castToMessage().leaf();\n        _insertAndSave(messageHash);\n        // Emit event with message information\n        emit Sent(messageHash, messageNonce, destination, msgPayload);\n        // Update the gas oracle data. We do this after the provided tips are checked so that\n        // the provided message is sent in the event that the gas oracle data is updated to a higher value.\n        InterfaceGasOracle(gasOracle).updateGasData(destination);\n        // TODO: consider doing this before the message is sent, while adjusting GasOracle.getMinimumTips() to\n        // use the pending gas oracle data.\n    }\n\n    /// @dev Returns the minimum tips for sending a message to the given destination with the given request and content.\n    function _getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        internal\n        view\n        returns (Tips)\n    {\n        return\n            TipsLib.wrapPadded(InterfaceGasOracle(gasOracle).getMinimumTips(destination, paddedRequest, contentLength));\n    }\n\n    /// @dev Gets the current gas data from the gas oracle to be saved as part of the Origin State.\n    function _fetchGasData() internal view override returns (GasData) {\n        return GasDataLib.wrapGasData(InterfaceGasOracle(gasOracle).getGasData());\n    }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"29101:34153:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;29101:34153:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"29101:34153:0:-:0;;;;;;;;","abiDefinition":[],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"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. Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing all math on `uint256` and `int256` and then downcasting.","kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"details\":\"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. Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing all math on `uint256` and `int256` and then downcasting.\",\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Origin.sol\":\"SafeCast\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Origin.sol\":{\"keccak256\":\"0x96775924f147f3d1f8df8cdf56731fe52a15af8d8e12e608efb8158c112b18cd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e642a27f5fab3c62b4c02e9754e9e42b1cf2e5381dbea9d3d106d23b7772ebe6\",\"dweb:/ipfs/QmUwn7ZyBvPkjnMuK8ZMSexBUdNQnVtxwyoAyT4DXLQjra\"]}},\"version\":1}"},"hashes":{}},"solidity/Origin.sol:StateHub":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/OriginEvents.sol\n\n/// @notice A collection of events emitted by the Origin contract\nabstract contract OriginEvents {\n    /**\n     * @notice Emitted when a new message is sent.\n     * @param messageHash   Hash of message; the leaf inserted to the Merkle tree for the message\n     * @param nonce         Nonce of sent message (starts from 1)\n     * @param destination   Destination domain\n     * @param message       Raw bytes of message\n     */\n    event Sent(bytes32 indexed messageHash, uint32 indexed nonce, uint32 indexed destination, bytes message);\n\n    /**\n     * @notice Emitted when a tip withdrawal is completed.\n     * @param actor     Actor address\n     * @param tip       Tip value, denominated in local domain's wei\n     */\n    event TipWithdrawalCompleted(address actor, uint256 tip);\n}\n\n// contracts/events/StateHubEvents.sol\n\n/// @notice A collection of events emitted by the StateHub contract\nabstract contract StateHubEvents {\n    /**\n     * @notice Emitted when a new Origin State is saved after a message was sent.\n     * @param state     Raw payload with state data\n     */\n    event StateSaved(bytes state);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n    /**\n     * @notice Check that a given state is valid: matches the historical state of Origin contract.\n     * Note: any Agent including an invalid state in their snapshot will be slashed\n     * upon providing the snapshot and agent signature for it to Origin contract.\n     * @dev Will revert if any of these is true:\n     *  - State payload is not properly formatted.\n     * @param statePayload      Raw payload with state data\n     * @return isValid          Whether the provided state is valid\n     */\n    function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns the amount of saved states so far.\n     * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n     */\n    function statesAmount() external view returns (uint256);\n\n    /**\n     * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @return statePayload     Raw payload with the latest state data\n     */\n    function suggestLatestState() external view returns (bytes memory statePayload);\n\n    /**\n     * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @param nonce             Historical nonce to form a state\n     * @return statePayload     Raw payload with historical state data\n     */\n    function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/InterfaceGasOracle.sol\n\ninterface InterfaceGasOracle {\n    /**\n     * @notice Fetches the latest gas data for the chain from `Destination` contract,\n     * and uses it to update the oracle values for the requested chain.\n     * @param domain    Domain to update the gas data for\n     */\n    function updateGasData(uint32 domain) external;\n\n    /**\n     * @notice Returns the gas data for the local chain.\n     */\n    function getGasData() external view returns (uint256 paddedGasData);\n\n    /**\n     * @notice Returns the gas data for the given domain, in the decoded format.\n     * @param domain        Domain of chain to get gas data for\n     * @return gasPrice     Gas price for the chain (in Wei per gas unit)\n     * @return dataPrice    Calldata price (in Wei per byte of content)\n     * @return execBuffer   Tx fee safety buffer for message execution (in Wei)\n     * @return amortAttCost Amortized cost for attestation submission (in Wei)\n     * @return etherPrice   Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n     * @return markup       Markup for the message execution (in BWAD)\n     */\n    function getDecodedGasData(uint32 domain)\n        external\n        view\n        returns (\n            uint256 gasPrice,\n            uint256 dataPrice,\n            uint256 execBuffer,\n            uint256 amortAttCost,\n            uint256 etherPrice,\n            uint256 markup\n        );\n\n    /**\n     * @notice Returns the minimum tips for sending a message to a given destination.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return paddedTips       Padded encoded minimum tips information\n     */\n    function getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 paddedTips);\n}\n\n// contracts/interfaces/InterfaceOrigin.sol\n\ninterface InterfaceOrigin {\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /**\n     * @notice Send a message to the recipient located on destination domain.\n     * @dev Recipient has to conform to IMessageRecipient interface, otherwise message won't be delivered.\n     * Will revert if any of these is true:\n     * - `destination` is equal to contract's local domain\n     * - `content` length is greater than `MAX_CONTENT_BYTES`\n     * - `msg.value` is lower than value of minimum tips for the given message\n     * @param destination           Domain of destination chain\n     * @param recipient             Address of recipient on destination chain as bytes32\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param paddedRequest         Padded encoded message execution request on destination chain\n     * @param content               Raw bytes content of message\n     * @return messageNonce         Nonce of the sent message\n     * @return messageHash          Hash of the sent message\n     */\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable returns (uint32 messageNonce, bytes32 messageHash);\n\n    /**\n     * @notice Send a manager message to the destination domain.\n     * @dev This could only be called by AgentManager, which takes care of encoding the calldata payload.\n     * Note: (msgOrigin, proofMaturity) security args will be added to payload on the destination chain\n     * so that the AgentManager could verify where the Manager Message came from and how mature is the proof.\n     * Note: function is not payable, as no tips are required for sending a manager message.\n     * Will revert if `destination` is equal to contract's local domain.\n     * @param destination           Domain of destination chain\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param payload               Payload for calling AgentManager on destination chain (with extra security args)\n     */\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        returns (uint32 messageNonce, bytes32 messageHash);\n\n    // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Withdraws locked base message tips to the recipient.\n     * @dev Could only be called by a local AgentManager.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function withdrawTips(address recipient, uint256 amount) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the minimum tips value for sending a message to a given destination.\n     * @dev Using at least `tipsValue` as `msg.value` for `sendBaseMessage()`\n     * will guarantee that the message will be accepted.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return tipsValue        Minimum tips value for a message to be accepted\n     */\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue);\n}\n\n// contracts/libs/Constants.sol\n\n// Here we define common constants to enable their easier reusing later.\n\n// ══════════════════════════════════ MERKLE ═══════════════════════════════════\n/// @dev Height of the Agent Merkle Tree\nuint256 constant AGENT_TREE_HEIGHT = 32;\n/// @dev Height of the Origin Merkle Tree\nuint256 constant ORIGIN_TREE_HEIGHT = 32;\n/// @dev Height of the Snapshot Merkle Tree. Allows up to 64 leafs, e.g. up to 32 states\nuint256 constant SNAPSHOT_TREE_HEIGHT = 6;\n// ══════════════════════════════════ STRUCTS ══════════════════════════════════\n/// @dev See Attestation.sol: (bytes32,bytes32,uint32,uint40,uint40): 32+32+4+5+5\nuint256 constant ATTESTATION_LENGTH = 78;\n/// @dev See GasData.sol: (uint16,uint16,uint16,uint16,uint16,uint16): 2+2+2+2+2+2\nuint256 constant GAS_DATA_LENGTH = 12;\n/// @dev See Receipt.sol: (uint32,uint32,bytes32,bytes32,uint8,address,address,address): 4+4+32+32+1+20+20+20\nuint256 constant RECEIPT_LENGTH = 133;\n/// @dev See State.sol: (bytes32,uint32,uint32,uint40,uint40,GasData): 32+4+4+5+5+len(GasData)\nuint256 constant STATE_LENGTH = 50 + GAS_DATA_LENGTH;\n/// @dev Maximum amount of states in a single snapshot. Each state produces two leafs in the tree\nuint256 constant SNAPSHOT_MAX_STATES = 1 \u003c\u003c (SNAPSHOT_TREE_HEIGHT - 1);\n// ══════════════════════════════════ MESSAGE ══════════════════════════════════\n/// @dev See Header.sol: (uint8,uint32,uint32,uint32,uint32): 1+4+4+4+4\nuint256 constant HEADER_LENGTH = 17;\n/// @dev See Request.sol: (uint96,uint64,uint32): 12+8+4\nuint256 constant REQUEST_LENGTH = 24;\n/// @dev See Tips.sol: (uint64,uint64,uint64,uint64): 8+8+8+8\nuint256 constant TIPS_LENGTH = 32;\n/// @dev The amount of discarded last bits when encoding tip values\nuint256 constant TIPS_GRANULARITY = 32;\n/// @dev Tip values could be only the multiples of TIPS_MULTIPLIER\nuint256 constant TIPS_MULTIPLIER = 1 \u003c\u003c TIPS_GRANULARITY;\n// ══════════════════════════════ STATEMENT SALTS ══════════════════════════════\n/// @dev Salts for signing various statements\nbytes32 constant ATTESTATION_VALID_SALT = keccak256(\"ATTESTATION_VALID_SALT\");\nbytes32 constant ATTESTATION_INVALID_SALT = keccak256(\"ATTESTATION_INVALID_SALT\");\nbytes32 constant RECEIPT_VALID_SALT = keccak256(\"RECEIPT_VALID_SALT\");\nbytes32 constant RECEIPT_INVALID_SALT = keccak256(\"RECEIPT_INVALID_SALT\");\nbytes32 constant SNAPSHOT_VALID_SALT = keccak256(\"SNAPSHOT_VALID_SALT\");\nbytes32 constant STATE_INVALID_SALT = keccak256(\"STATE_INVALID_SALT\");\n// ═════════════════════════════════ PROTOCOL ══════════════════════════════════\n/// @dev Optimistic period for new agent roots in LightManager\nuint32 constant AGENT_ROOT_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Timeout between the agent root could be proposed and resolved in LightManager\nuint32 constant AGENT_ROOT_PROPOSAL_TIMEOUT = 12 hours;\nuint32 constant BONDING_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Amount of time that the Notary will not be considered active after they won a dispute\nuint32 constant DISPUTE_TIMEOUT_NOTARY = 12 hours;\n/// @dev Amount of time without fresh data from Notaries before contract owner can resolve stuck disputes manually\nuint256 constant FRESH_DATA_TIMEOUT = 4 hours;\n/// @dev Maximum bytes per message = 2 KiB (somewhat arbitrarily set to begin)\nuint256 constant MAX_CONTENT_BYTES = 2 * 2 ** 10;\n/// @dev Maximum value for the summit tip that could be set in GasOracle\nuint256 constant MAX_SUMMIT_TIP = 0.01 ether;\n\n// contracts/libs/Errors.sol\n\n// ══════════════════════════════ INVALID CALLER ═══════════════════════════════\n\nerror CallerNotAgentManager();\nerror CallerNotDestination();\nerror CallerNotInbox();\nerror CallerNotSummit();\n\n// ══════════════════════════════ INCORRECT DATA ═══════════════════════════════\n\nerror IncorrectAttestation();\nerror IncorrectAgentDomain();\nerror IncorrectAgentIndex();\nerror IncorrectAgentProof();\nerror IncorrectAgentRoot();\nerror IncorrectDataHash();\nerror IncorrectDestinationDomain();\nerror IncorrectOriginDomain();\nerror IncorrectSnapshotProof();\nerror IncorrectSnapshotRoot();\nerror IncorrectState();\nerror IncorrectStatesAmount();\nerror IncorrectTipsProof();\nerror IncorrectVersionLength();\n\nerror IncorrectNonce();\nerror IncorrectSender();\nerror IncorrectRecipient();\n\nerror FlagOutOfRange();\nerror IndexOutOfRange();\nerror NonceOutOfRange();\n\nerror OutdatedNonce();\n\nerror UnformattedAttestation();\nerror UnformattedAttestationReport();\nerror UnformattedBaseMessage();\nerror UnformattedCallData();\nerror UnformattedCallDataPrefix();\nerror UnformattedMessage();\nerror UnformattedReceipt();\nerror UnformattedReceiptReport();\nerror UnformattedSignature();\nerror UnformattedSnapshot();\nerror UnformattedState();\nerror UnformattedStateReport();\n\n// ═══════════════════════════════ MERKLE TREES ════════════════════════════════\n\nerror LeafNotProven();\nerror MerkleTreeFull();\nerror NotEnoughLeafs();\nerror TreeHeightTooLow();\n\n// ═════════════════════════════ OPTIMISTIC PERIOD ═════════════════════════════\n\nerror BaseClientOptimisticPeriod();\nerror MessageOptimisticPeriod();\nerror SlashAgentOptimisticPeriod();\nerror WithdrawTipsOptimisticPeriod();\nerror ZeroProofMaturity();\n\n// ═══════════════════════════════ AGENT MANAGER ═══════════════════════════════\n\nerror AgentNotGuard();\nerror AgentNotNotary();\n\nerror AgentCantBeAdded();\nerror AgentNotActive();\nerror AgentNotActiveNorUnstaking();\nerror AgentNotFraudulent();\nerror AgentNotUnstaking();\nerror AgentUnknown();\n\nerror AgentRootNotProposed();\nerror AgentRootTimeoutNotOver();\n\nerror NotStuck();\n\nerror DisputeAlreadyResolved();\nerror DisputeNotOpened();\nerror DisputeTimeoutNotOver();\nerror GuardInDispute();\nerror NotaryInDispute();\n\nerror MustBeSynapseDomain();\nerror SynapseDomainForbidden();\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\nerror AlreadyExecuted();\nerror AlreadyFailed();\nerror DuplicatedSnapshotRoot();\nerror IncorrectMagicValue();\nerror GasLimitTooLow();\nerror GasSuppliedTooLow();\n\n// ══════════════════════════════════ ORIGIN ═══════════════════════════════════\n\nerror ContentLengthTooBig();\nerror EthTransferFailed();\nerror InsufficientEthBalance();\n\n// ════════════════════════════════ GAS ORACLE ═════════════════════════════════\n\nerror LocalGasDataNotSet();\nerror RemoteGasDataNotSet();\n\n// ═══════════════════════════════════ TIPS ════════════════════════════════════\n\nerror SummitTipTooHigh();\nerror TipsClaimMoreThanEarned();\nerror TipsClaimZero();\nerror TipsOverflow();\nerror TipsValueTooLow();\n\n// ════════════════════════════════ MEMORY VIEW ════════════════════════════════\n\nerror IndexedTooMuch();\nerror ViewOverrun();\nerror OccupiedMemory();\nerror UnallocatedMemory();\nerror PrecompileOutOfGas();\n\n// ═════════════════════════════════ MULTICALL ═════════════════════════════════\n\nerror MulticallFailed();\n\n// contracts/libs/TypeCasts.sol\n\nlibrary TypeCasts {\n    // alignment preserving cast\n    function addressToBytes32(address addr) internal pure returns (bytes32) {\n        return bytes32(uint256(uint160(addr)));\n    }\n\n    // alignment preserving cast\n    function bytes32ToAddress(bytes32 buf) internal pure returns (address) {\n        return address(uint160(uint256(buf)));\n    }\n}\n\n// contracts/libs/stack/Number.sol\n\n/// Number is a compact representation of uint256, that is fit into 16 bits\n/// with the maximum relative error under 0.4%.\ntype Number is uint16;\n\nusing NumberLib for Number global;\n\n/// # Number\n/// Library for compact representation of uint256 numbers.\n/// - Number is stored using mantissa and exponent, each occupying 8 bits.\n/// - Numbers under 2**8 are stored as `mantissa` with `exponent = 0xFF`.\n/// - Numbers at least 2**8 are approximated as `(256 + mantissa) \u003c\u003c exponent`\n/// \u003e - `0 \u003c= mantissa \u003c 256`\n/// \u003e - `0 \u003c= exponent \u003c= 247` (`256 * 2**248` doesn't fit into uint256)\n/// # Number stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type  | Bytes |\n/// | ---------- | -------- | ----- | ----- |\n/// | (002..001] | mantissa | uint8 | 1     |\n/// | (001..000] | exponent | uint8 | 1     |\n\nlibrary NumberLib {\n    /// @dev Amount of bits to shift to mantissa field\n    uint16 private constant SHIFT_MANTISSA = 8;\n\n    /// @notice For bwad math (binary wad) we use 2**64 as \"wad\" unit.\n    /// @dev We are using not using 10**18 as wad, because it is not stored precisely in NumberLib.\n    uint256 internal constant BWAD_SHIFT = 64;\n    uint256 internal constant BWAD = 1 \u003c\u003c BWAD_SHIFT;\n    /// @notice ~0.1% in bwad units.\n    uint256 internal constant PER_MILLE_SHIFT = BWAD_SHIFT - 10;\n    uint256 internal constant PER_MILLE = 1 \u003c\u003c PER_MILLE_SHIFT;\n\n    /// @notice Compresses uint256 number into 16 bits.\n    function compress(uint256 value) internal pure returns (Number) {\n        // Find `msb` such as `2**msb \u003c= value \u003c 2**(msb + 1)`\n        uint256 msb = mostSignificantBit(value);\n        // We want to preserve 9 bits of precision.\n        // The highest bit is always 1, so we can skip it.\n        // The remaining 8 highest bits are stored as mantissa.\n        if (msb \u003c 8) {\n            // Value is less than 2**8, so we can use value as mantissa with \"-1\" exponent.\n            return _encode(uint8(value), 0xFF);\n        } else {\n            // We use `msb - 8` as exponent otherwise. Note that `exponent \u003e= 0`.\n            unchecked {\n                uint256 exponent = msb - 8;\n                // Shifting right by `msb-8` bits will shift the \"remaining 8 highest bits\" into the 8 lowest bits.\n                // uint8() will truncate the highest bit.\n                return _encode(uint8(value \u003e\u003e exponent), uint8(exponent));\n            }\n        }\n    }\n\n    /// @notice Decompresses 16 bits number into uint256.\n    /// @dev The outcome is an approximation of the original number: `(value - value / 256) \u003c number \u003c= value`.\n    function decompress(Number number) internal pure returns (uint256 value) {\n        // Isolate 8 highest bits as the mantissa.\n        uint256 mantissa = Number.unwrap(number) \u003e\u003e SHIFT_MANTISSA;\n        // This will truncate the highest bits, leaving only the exponent.\n        uint256 exponent = uint8(Number.unwrap(number));\n        if (exponent == 0xFF) {\n            return mantissa;\n        } else {\n            unchecked {\n                return (256 + mantissa) \u003c\u003c (exponent);\n            }\n        }\n    }\n\n    /// @dev Returns the most significant bit of `x`\n    /// https://solidity-by-example.org/bitwise/\n    function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\n        // To find `msb` we determine it bit by bit, starting from the highest one.\n        // `0 \u003c= msb \u003c= 255`, so we start from the highest bit, 1\u003c\u003c7 == 128.\n        // If `x` is at least 2**128, then the highest bit of `x` is at least 128.\n        // solhint-disable no-inline-assembly\n        assembly {\n            // `f` is set to 1\u003c\u003c7 if `x \u003e= 2**128` and to 0 otherwise.\n            let f := shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\n            // If `x \u003e= 2**128` then set `msb` highest bit to 1 and shift `x` right by 128.\n            // Otherwise, `msb` remains 0 and `x` remains unchanged.\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        // `x` is now at most 2**128 - 1. Continue the same way, the next highest bit is 1\u003c\u003c6 == 64.\n        assembly {\n            // `f` is set to 1\u003c\u003c6 if `x \u003e= 2**64` and to 0 otherwise.\n            let f := shl(6, gt(x, 0xFFFFFFFFFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c5 if `x \u003e= 2**32` and to 0 otherwise.\n            let f := shl(5, gt(x, 0xFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c4 if `x \u003e= 2**16` and to 0 otherwise.\n            let f := shl(4, gt(x, 0xFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c3 if `x \u003e= 2**8` and to 0 otherwise.\n            let f := shl(3, gt(x, 0xFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c2 if `x \u003e= 2**4` and to 0 otherwise.\n            let f := shl(2, gt(x, 0xF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c1 if `x \u003e= 2**2` and to 0 otherwise.\n            let f := shl(1, gt(x, 0x3))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1 if `x \u003e= 2**1` and to 0 otherwise.\n            let f := gt(x, 0x1)\n            msb := or(msb, f)\n        }\n    }\n\n    /// @dev Wraps (mantissa, exponent) pair into Number.\n    function _encode(uint8 mantissa, uint8 exponent) private pure returns (Number) {\n        // Casts below are upcasts, so they are safe.\n        return Number.wrap(uint16(mantissa) \u003c\u003c SHIFT_MANTISSA | uint16(exponent));\n    }\n}\n\n// contracts/libs/stack/Request.sol\n\n/// Request is encoded data with \"message execution request\".\ntype Request is uint192;\n\nusing RequestLib for Request global;\n\n/// Library for formatting _the request part_ of _the base messages_.\n/// - Request represents a message sender requirements for the message execution on the destination chain.\n/// - Request occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n/// \u003e gasDrop field is included for future compatibility and is ignored at the moment.\n///\n/// # Request stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type   | Bytes | Description                                          |\n/// | ---------- | -------- | ------ | ----- | ---------------------------------------------------- |\n/// | (024..012] | gasDrop  | uint96 | 12    | Minimum amount of gas token to drop to the recipient |\n/// | (012..004] | gasLimit | uint64 | 8     | Minimum amount of gas units to supply for execution  |\n/// | (004..000] | version  | uint32 | 4     | Base message version to pass to the recipient        |\n\nlibrary RequestLib {\n    /// @dev Amount of bits to shift to gasDrop field\n    uint192 private constant SHIFT_GAS_DROP = 12 * 8;\n    /// @dev Amount of bits to shift to gasLimit field\n    uint192 private constant SHIFT_GAS_LIMIT = 4 * 8;\n\n    /// @notice Returns an encoded request with the given fields\n    /// @param gasDrop_     Minimum amount of gas token to drop to the recipient (ignored at the moment)\n    /// @param gasLimit_    Minimum amount of gas units to supply for execution\n    /// @param version_     Base message version to pass to the recipient\n    function encodeRequest(uint96 gasDrop_, uint64 gasLimit_, uint32 version_) internal pure returns (Request) {\n        // Casts below are upcasts, so they are safe\n        return Request.wrap(uint192(gasDrop_) \u003c\u003c SHIFT_GAS_DROP | uint192(gasLimit_) \u003c\u003c SHIFT_GAS_LIMIT | version_);\n    }\n\n    /// @notice Wraps the padded encoded request into a Request-typed value.\n    /// @dev The \"padded\" request is simply an encoded request casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded requests\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedRequest) internal pure returns (Request) {\n        // Casting to uint192 will truncate the highest bits, which is the behavior we want\n        return Request.wrap(uint192(paddedRequest));\n    }\n\n    /// @notice Returns the requested of gas token to drop to the recipient.\n    function gasDrop(Request request) internal pure returns (uint96) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return uint96(Request.unwrap(request) \u003e\u003e SHIFT_GAS_DROP);\n    }\n\n    /// @notice Returns the requested minimum amount of gas units to supply for execution.\n    function gasLimit(Request request) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Request.unwrap(request) \u003e\u003e SHIFT_GAS_LIMIT);\n    }\n\n    /// @notice Returns the requested base message version to pass to the recipient.\n    function version(Request request) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Request.unwrap(request));\n    }\n}\n\n// node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        require(value \u003c= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        require(value \u003c= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        require(value \u003c= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value \u003c= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        require(value \u003c= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        require(value \u003c= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        require(value \u003c= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        require(value \u003c= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        require(value \u003c= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        require(value \u003c= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        require(value \u003c= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        require(value \u003c= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        require(value \u003c= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        require(value \u003c= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        require(value \u003c= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value \u003c= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        require(value \u003c= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        require(value \u003c= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        require(value \u003c= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value \u003c= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        require(value \u003c= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        require(value \u003c= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        require(value \u003c= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value \u003c= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        require(value \u003c= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        require(value \u003c= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        require(value \u003c= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value \u003c= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        require(value \u003c= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value \u003c= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value \u003c= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     *\n     * _Available since v3.0._\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value \u003e= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     *\n     * _Available since v3.0._\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value \u003c= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     *\n     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length \u003e 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance \u003e= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance \u003e= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length \u003e 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n\n// contracts/base/MultiCallable.sol\n\n/// @notice Collection of Multicall utilities. Fork of Multicall3:\n/// https://github.com/mds1/multicall/blob/master/src/Multicall3.sol\nabstract contract MultiCallable {\n    struct Call {\n        bool allowFailure;\n        bytes callData;\n    }\n\n    struct Result {\n        bool success;\n        bytes returnData;\n    }\n\n    /// @notice Aggregates a few calls to this contract into one multicall without modifying `msg.sender`.\n    function multicall(Call[] calldata calls) external returns (Result[] memory callResults) {\n        uint256 amount = calls.length;\n        callResults = new Result[](amount);\n        Call calldata call_;\n        for (uint256 i = 0; i \u003c amount;) {\n            call_ = calls[i];\n            Result memory result = callResults[i];\n            // We perform a delegate call to ourselves here. Delegate call does not modify `msg.sender`, so\n            // this will have the same effect as if `msg.sender` performed all the calls themselves one by one.\n            // solhint-disable-next-line avoid-low-level-calls\n            (result.success, result.returnData) = address(this).delegatecall(call_.callData);\n            // solhint-disable-next-line no-inline-assembly\n            assembly {\n                // Revert if the call fails and failure is not allowed\n                // `allowFailure := calldataload(call_)` and `success := mload(result)`\n                if iszero(or(calldataload(call_), mload(result))) {\n                    // Revert with `0x4d6a2328` (function selector for `MulticallFailed()`)\n                    mstore(0x00, 0x4d6a232800000000000000000000000000000000000000000000000000000000)\n                    revert(0x00, 0x04)\n                }\n            }\n            unchecked {\n                ++i;\n            }\n        }\n    }\n}\n\n// contracts/base/Version.sol\n\n/**\n * @title Versioned\n * @notice Version getter for contracts. Doesn't use any storage slots, meaning\n * it will never cause any troubles with the upgradeable contracts. For instance, this contract\n * can be added or removed from the inheritance chain without shifting the storage layout.\n */\nabstract contract Versioned {\n    /**\n     * @notice Struct that is mimicking the storage layout of a string with 32 bytes or less.\n     * Length is limited by 32, so the whole string payload takes two memory words:\n     * @param length    String length\n     * @param data      String characters\n     */\n    struct _ShortString {\n        uint256 length;\n        bytes32 data;\n    }\n\n    /// @dev Length of the \"version string\"\n    uint256 private immutable _length;\n    /// @dev Bytes representation of the \"version string\".\n    /// Strings with length over 32 are not supported!\n    bytes32 private immutable _data;\n\n    constructor(string memory version_) {\n        _length = bytes(version_).length;\n        if (_length \u003e 32) revert IncorrectVersionLength();\n        // bytes32 is left-aligned =\u003e this will store the byte representation of the string\n        // with the trailing zeroes to complete the 32-byte word\n        _data = bytes32(bytes(version_));\n    }\n\n    function version() external view returns (string memory versionString) {\n        // Load the immutable values to form the version string\n        _ShortString memory str = _ShortString(_length, _data);\n        // The only way to do this cast is doing some dirty assembly\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            versionString := str\n        }\n    }\n}\n\n// contracts/libs/ChainContext.sol\n\n/// @notice Library for accessing chain context variables as tightly packed integers.\n/// Messaging contracts should rely on this library for accessing chain context variables\n/// instead of doing the casting themselves.\nlibrary ChainContext {\n    using SafeCast for uint256;\n\n    /// @notice Returns the current block number as uint40.\n    /// @dev Reverts if block number is greater than 40 bits, which is not supposed to happen\n    /// until the block.timestamp overflows (assuming block time is at least 1 second).\n    function blockNumber() internal view returns (uint40) {\n        return block.number.toUint40();\n    }\n\n    /// @notice Returns the current block timestamp as uint40.\n    /// @dev Reverts if block timestamp is greater than 40 bits, which is\n    /// supposed to happen approximately in year 36835.\n    function blockTimestamp() internal view returns (uint40) {\n        return block.timestamp.toUint40();\n    }\n\n    /// @notice Returns the chain id as uint32.\n    /// @dev Reverts if chain id is greater than 32 bits, which is not\n    /// supposed to happen in production.\n    function chainId() internal view returns (uint32) {\n        return block.chainid.toUint32();\n    }\n}\n\n// contracts/libs/Structures.sol\n\n// Here we define common enums and structures to enable their easier reusing later.\n\n// ═══════════════════════════════ AGENT STATUS ════════════════════════════════\n\n/// @dev Potential statuses for the off-chain bonded agent:\n/// - Unknown: never provided a bond =\u003e signature not valid\n/// - Active: has a bond in BondingManager =\u003e signature valid\n/// - Unstaking: has a bond in BondingManager, initiated the unstaking =\u003e signature not valid\n/// - Resting: used to have a bond in BondingManager, successfully unstaked =\u003e signature not valid\n/// - Fraudulent: proven to commit fraud, value in Merkle Tree not updated =\u003e signature not valid\n/// - Slashed: proven to commit fraud, value in Merkle Tree was updated =\u003e signature not valid\n/// Unstaked agent could later be added back to THE SAME domain by staking a bond again.\n/// Honest agent: Unknown -\u003e Active -\u003e unstaking -\u003e Resting -\u003e Active ...\n/// Malicious agent: Unknown -\u003e Active -\u003e Fraudulent -\u003e Slashed\n/// Malicious agent: Unknown -\u003e Active -\u003e Unstaking -\u003e Fraudulent -\u003e Slashed\nenum AgentFlag {\n    Unknown,\n    Active,\n    Unstaking,\n    Resting,\n    Fraudulent,\n    Slashed\n}\n\n/// @notice Struct for storing an agent in the BondingManager contract.\nstruct AgentStatus {\n    AgentFlag flag;\n    uint32 domain;\n    uint32 index;\n}\n// 184 bits available for tight packing\n\nusing StructureUtils for AgentStatus global;\n\n/// @notice Potential statuses of an agent in terms of being in dispute\n/// - None: agent is not in dispute\n/// - Pending: agent is in unresolved dispute\n/// - Slashed: agent was in dispute that lead to agent being slashed\n/// Note: agent who won the dispute has their status reset to None\nenum DisputeFlag {\n    None,\n    Pending,\n    Slashed\n}\n\n/// @notice Struct for storing dispute status of an agent.\n/// @param flag         Dispute flag: None/Pending/Slashed.\n/// @param openedAt     Timestamp when the latest agent dispute was opened (zero if not opened).\n/// @param resolvedAt   Timestamp when the latest agent dispute was resolved (zero if not resolved).\nstruct DisputeStatus {\n    DisputeFlag flag;\n    uint40 openedAt;\n    uint40 resolvedAt;\n}\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\n/// @notice Struct representing the status of Destination contract.\n/// @param snapRootTime     Timestamp when latest snapshot root was accepted\n/// @param agentRootTime    Timestamp when latest agent root was accepted\n/// @param notaryIndex      Index of Notary who signed the latest agent root\nstruct DestinationStatus {\n    uint40 snapRootTime;\n    uint40 agentRootTime;\n    uint32 notaryIndex;\n}\n\n// ═══════════════════════════════ EXECUTION HUB ═══════════════════════════════\n\n/// @notice Potential statuses of the message in Execution Hub.\n/// - None: there hasn't been a valid attempt to execute the message yet\n/// - Failed: there was a valid attempt to execute the message, but recipient reverted\n/// - Success: there was a valid attempt to execute the message, and recipient did not revert\n/// Note: message can be executed until its status is Success\nenum MessageStatus {\n    None,\n    Failed,\n    Success\n}\n\nlibrary StructureUtils {\n    /// @notice Checks that Agent is Active\n    function verifyActive(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active) {\n            revert AgentNotActive();\n        }\n    }\n\n    /// @notice Checks that Agent is Unstaking\n    function verifyUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Unstaking) {\n            revert AgentNotUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Active or Unstaking\n    function verifyActiveUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active \u0026\u0026 status.flag != AgentFlag.Unstaking) {\n            revert AgentNotActiveNorUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Fraudulent\n    function verifyFraudulent(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Fraudulent) {\n            revert AgentNotFraudulent();\n        }\n    }\n\n    /// @notice Checks that Agent is not Unknown\n    function verifyKnown(AgentStatus memory status) internal pure {\n        if (status.flag == AgentFlag.Unknown) {\n            revert AgentUnknown();\n        }\n    }\n}\n\n// contracts/libs/memory/MemView.sol\n\n/// @dev MemView is an untyped view over a portion of memory to be used instead of `bytes memory`\ntype MemView is uint256;\n\n/// @dev Attach library functions to MemView\nusing MemViewLib for MemView global;\n\n/// @notice Library for operations with the memory views.\n/// Forked from https://github.com/summa-tx/memview-sol with several breaking changes:\n/// - The codebase is ported to Solidity 0.8\n/// - Custom errors are added\n/// - The runtime type checking is replaced with compile-time check provided by User-Defined Value Types\n///   https://docs.soliditylang.org/en/latest/types.html#user-defined-value-types\n/// - uint256 is used as the underlying type for the \"memory view\" instead of bytes29.\n///   It is wrapped into MemView custom type in order not to be confused with actual integers.\n/// - Therefore the \"type\" field is discarded, allowing to allocate 16 bytes for both view location and length\n/// - The documentation is expanded\n/// - Library functions unused by the rest of the codebase are removed\n//  - Very pretty code separators are added :)\nlibrary MemViewLib {\n    /// @notice Stack layout for uint256 (from highest bits to lowest)\n    /// (32 .. 16]      loc     16 bytes    Memory address of underlying bytes\n    /// (16 .. 00]      len     16 bytes    Length of underlying bytes\n\n    // ═══════════════════════════════════════════ BUILDING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Instantiate a new untyped memory view. This should generally not be called directly.\n     * Prefer `ref` wherever possible.\n     * @param loc_          The memory address\n     * @param len_          The length\n     * @return The new view with the specified location and length\n     */\n    function build(uint256 loc_, uint256 len_) internal pure returns (MemView) {\n        uint256 end_ = loc_ + len_;\n        // Make sure that a view is not constructed that points to unallocated memory\n        // as this could be indicative of a buffer overflow attack\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            if gt(end_, mload(0x40)) { end_ := 0 }\n        }\n        if (end_ == 0) {\n            revert UnallocatedMemory();\n        }\n        return _unsafeBuildUnchecked(loc_, len_);\n    }\n\n    /**\n     * @notice Instantiate a memory view from a byte array.\n     * @dev Note that due to Solidity memory representation, it is not possible to\n     * implement a deref, as the `bytes` type stores its len in memory.\n     * @param arr           The byte array\n     * @return The memory view over the provided byte array\n     */\n    function ref(bytes memory arr) internal pure returns (MemView) {\n        uint256 len_ = arr.length;\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 loc_;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // We add 0x20, so that the view starts exactly where the array data starts\n            loc_ := add(arr, 0x20)\n        }\n        return build(loc_, len_);\n    }\n\n    // ════════════════════════════════════════════ CLONING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to the new memory.\n     * @param memView       The memory view\n     * @return arr          The cloned byte array\n     */\n    function clone(MemView memView) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        unchecked {\n            _unsafeCopyTo(memView, ptr + 0x20);\n        }\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 len_ = memView.len();\n        uint256 footprint_ = memView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    /**\n     * @notice Copies all views, joins them into a new bytearray.\n     * @param memViews      The memory views\n     * @return arr          The new byte array with joined data behind the given views\n     */\n    function join(MemView[] memory memViews) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        MemView newView;\n        unchecked {\n            newView = _unsafeJoin(memViews, ptr + 0x20);\n        }\n        uint256 len_ = newView.len();\n        uint256 footprint_ = newView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    // ══════════════════════════════════════════ INSPECTING MEMORY VIEW ═══════════════════════════════════════════════\n\n    /**\n     * @notice Returns the memory address of the underlying bytes.\n     * @param memView       The memory view\n     * @return loc_         The memory address\n     */\n    function loc(MemView memView) internal pure returns (uint256 loc_) {\n        // loc is stored in the highest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u003e\u003e 128;\n    }\n\n    /**\n     * @notice Returns the number of bytes of the view.\n     * @param memView       The memory view\n     * @return len_         The length of the view\n     */\n    function len(MemView memView) internal pure returns (uint256 len_) {\n        // len is stored in the lowest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u0026 type(uint128).max;\n    }\n\n    /**\n     * @notice Returns the endpoint of `memView`.\n     * @param memView       The memory view\n     * @return end_         The endpoint of `memView`\n     */\n    function end(MemView memView) internal pure returns (uint256 end_) {\n        // The endpoint never overflows uint128, let alone uint256, so we could use unchecked math here\n        unchecked {\n            return memView.loc() + memView.len();\n        }\n    }\n\n    /**\n     * @notice Returns the number of memory words this memory view occupies, rounded up.\n     * @param memView       The memory view\n     * @return words_       The number of memory words\n     */\n    function words(MemView memView) internal pure returns (uint256 words_) {\n        // returning ceil(length / 32.0)\n        unchecked {\n            return (memView.len() + 31) \u003e\u003e 5;\n        }\n    }\n\n    /**\n     * @notice Returns the in-memory footprint of a fresh copy of the view.\n     * @param memView       The memory view\n     * @return footprint_   The in-memory footprint of a fresh copy of the view.\n     */\n    function footprint(MemView memView) internal pure returns (uint256 footprint_) {\n        // words() * 32\n        return memView.words() \u003c\u003c 5;\n    }\n\n    // ════════════════════════════════════════════ HASHING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the keccak256 hash of the underlying memory\n     * @param memView       The memory view\n     * @return digest       The keccak256 hash of the underlying memory\n     */\n    function keccak(MemView memView) internal pure returns (bytes32 digest) {\n        uint256 loc_ = memView.loc();\n        uint256 len_ = memView.len();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            digest := keccak256(loc_, len_)\n        }\n    }\n\n    /**\n     * @notice Adds a salt to the keccak256 hash of the underlying data and returns the keccak256 hash of the\n     * resulting data.\n     * @param memView       The memory view\n     * @return digestSalted keccak256(salt, keccak256(memView))\n     */\n    function keccakSalted(MemView memView, bytes32 salt) internal pure returns (bytes32 digestSalted) {\n        return keccak256(bytes.concat(salt, memView.keccak()));\n    }\n\n    // ════════════════════════════════════════════ SLICING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Safe slicing without memory modification.\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the given index\n     */\n    function slice(MemView memView, uint256 index_, uint256 len_) internal pure returns (MemView) {\n        uint256 loc_ = memView.loc();\n        // Ensure it doesn't overrun the view\n        if (loc_ + index_ + len_ \u003e memView.end()) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // loc_ + index_ \u003c= memView.end()\n            return build({loc_: loc_ + index_, len_: len_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing bytes from `index` to end(memView).\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @return The new view for the slice starting from the given index until the initial view endpoint\n     */\n    function sliceFrom(MemView memView, uint256 index_) internal pure returns (MemView) {\n        uint256 len_ = memView.len();\n        // Ensure it doesn't overrun the view\n        if (index_ \u003e len_) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // index_ \u003c= len_ =\u003e memView.loc() + index_ \u003c= memView.loc() + memView.len() == memView.end()\n            return build({loc_: memView.loc() + index_, len_: len_ - index_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the first `len` bytes.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the initial view beginning\n     */\n    function prefix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        return memView.slice({index_: 0, len_: len_});\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the last `len` byte.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length until the initial view endpoint\n     */\n    function postfix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        uint256 viewLen = memView.len();\n        // Ensure it doesn't overrun the view\n        if (len_ \u003e viewLen) {\n            revert ViewOverrun();\n        }\n        // Could do the unchecked math due to the check above\n        uint256 index_;\n        unchecked {\n            index_ = viewLen - len_;\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // len_ \u003c= memView.len() =\u003e memView.loc() \u003c= loc_ \u003c= memView.end()\n            return build({loc_: memView.loc() + viewLen - len_, len_: len_});\n        }\n    }\n\n    // ═══════════════════════════════════════════ INDEXING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Load up to 32 bytes from the view onto the stack.\n     * @dev Returns a bytes32 with only the `bytes_` HIGHEST bytes set.\n     * This can be immediately cast to a smaller fixed-length byte array.\n     * To automatically cast to an integer, use `indexUint`.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return result       The 32 byte result having only `bytes_` highest bytes set\n     */\n    function index(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (bytes32 result) {\n        if (bytes_ == 0) {\n            return bytes32(0);\n        }\n        // Can't load more than 32 bytes to the stack in one go\n        if (bytes_ \u003e 32) {\n            revert IndexedTooMuch();\n        }\n        // The last indexed byte should be within view boundaries\n        if (index_ + bytes_ \u003e memView.len()) {\n            revert ViewOverrun();\n        }\n        uint256 bitLength = bytes_ \u003c\u003c 3; // bytes_ * 8\n        uint256 loc_ = memView.loc();\n        // Get a mask with `bitLength` highest bits set\n        uint256 mask;\n        // 0x800...00 binary representation is 100...00\n        // sar stands for \"signed arithmetic shift\": https://en.wikipedia.org/wiki/Arithmetic_shift\n        // sar(N-1, 100...00) = 11...100..00, with exactly N highest bits set to 1\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            mask := sar(sub(bitLength, 1), 0x8000000000000000000000000000000000000000000000000000000000000000)\n        }\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load a full word using index offset, and apply mask to ignore non-relevant bytes\n            result := and(mload(add(loc_, index_)), mask)\n        }\n    }\n\n    /**\n     * @notice Parse an unsigned integer from the view at `index`.\n     * @dev Requires that the view have \u003e= `bytes_` bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return The unsigned integer\n     */\n    function indexUint(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (uint256) {\n        bytes32 indexedBytes = memView.index(index_, bytes_);\n        // `index()` returns left-aligned `bytes_`, while integers are right-aligned\n        // Shifting here to right-align with the full 32 bytes word: need to shift right `(32 - bytes_)` bytes\n        unchecked {\n            // memView.index() reverts when bytes_ \u003e 32, thus unchecked math\n            return uint256(indexedBytes) \u003e\u003e ((32 - bytes_) \u003c\u003c 3);\n        }\n    }\n\n    /**\n     * @notice Parse an address from the view at `index`.\n     * @dev Requires that the view have \u003e= 20 bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @return The address\n     */\n    function indexAddress(MemView memView, uint256 index_) internal pure returns (address) {\n        // index 20 bytes as `uint160`, and then cast to `address`\n        return address(uint160(memView.indexUint(index_, 20)));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns a memory view over the specified memory location\n    /// without checking if it points to unallocated memory.\n    function _unsafeBuildUnchecked(uint256 loc_, uint256 len_) private pure returns (MemView) {\n        // There is no scenario where loc or len would overflow uint128, so we omit this check.\n        // We use the highest 128 bits to encode the location and the lowest 128 bits to encode the length.\n        return MemView.wrap((loc_ \u003c\u003c 128) | len_);\n    }\n\n    /**\n     * @notice Copy the view to a location, return an unsafe memory reference\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memView       The memory view\n     * @param newLoc        The new location to copy the underlying view data\n     * @return The memory view over the unsafe memory with the copied underlying data\n     */\n    function _unsafeCopyTo(MemView memView, uint256 newLoc) private view returns (MemView) {\n        uint256 len_ = memView.len();\n        uint256 oldLoc = memView.loc();\n\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (newLoc \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        bool res;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // use the identity precompile (0x04) to copy\n            res := staticcall(gas(), 0x04, oldLoc, len_, newLoc, len_)\n        }\n        if (!res) revert PrecompileOutOfGas();\n        return _unsafeBuildUnchecked({loc_: newLoc, len_: len_});\n    }\n\n    /**\n     * @notice Join the views in memory, return an unsafe reference to the memory.\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memViews      The memory views\n     * @return The conjoined view pointing to the new memory\n     */\n    function _unsafeJoin(MemView[] memory memViews, uint256 location) private view returns (MemView) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (location \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        // Copy the views to the specified location one by one, by tracking the amount of copied bytes so far\n        uint256 offset = 0;\n        for (uint256 i = 0; i \u003c memViews.length;) {\n            MemView memView = memViews[i];\n            // We can use the unchecked math here as location + sum(view.length) will never overflow uint256\n            unchecked {\n                _unsafeCopyTo(memView, location + offset);\n                offset += memView.len();\n                ++i;\n            }\n        }\n        return _unsafeBuildUnchecked({loc_: location, len_: offset});\n    }\n}\n\n// contracts/libs/merkle/MerkleMath.sol\n\nlibrary MerkleMath {\n    // ═════════════════════════════════════════ BASIC MERKLE CALCULATIONS ═════════════════════════════════════════════\n\n    /**\n     * @notice Calculates the merkle root for the given leaf and merkle proof.\n     * @dev Will revert if proof length exceeds the tree height.\n     * @param index     Index of `leaf` in tree\n     * @param leaf      Leaf of the merkle tree\n     * @param proof     Proof of inclusion of `leaf` in the tree\n     * @param height    Height of the merkle tree\n     * @return root_    Calculated Merkle Root\n     */\n    function proofRoot(uint256 index, bytes32 leaf, bytes32[] memory proof, uint256 height)\n        internal\n        pure\n        returns (bytes32 root_)\n    {\n        // Proof length could not exceed the tree height\n        uint256 proofLen = proof.length;\n        if (proofLen \u003e height) revert TreeHeightTooLow();\n        root_ = leaf;\n        /// @dev Apply unchecked to all ++h operations\n        unchecked {\n            // Go up the tree levels from the leaf following the proof\n            for (uint256 h = 0; h \u003c proofLen; ++h) {\n                // Get a sibling node on current level: this is proof[h]\n                root_ = getParent(root_, proof[h], index, h);\n            }\n            // Go up to the root: the remaining siblings are EMPTY\n            for (uint256 h = proofLen; h \u003c height; ++h) {\n                root_ = getParent(root_, bytes32(0), index, h);\n            }\n        }\n    }\n\n    /**\n     * @notice Calculates the parent of a node on the path from one of the leafs to root.\n     * @param node          Node on a path from tree leaf to root\n     * @param sibling       Sibling for a given node\n     * @param leafIndex     Index of the tree leaf\n     * @param nodeHeight    \"Level height\" for `node` (ZERO for leafs, ORIGIN_TREE_HEIGHT for root)\n     */\n    function getParent(bytes32 node, bytes32 sibling, uint256 leafIndex, uint256 nodeHeight)\n        internal\n        pure\n        returns (bytes32 parent)\n    {\n        // Index for `node` on its \"tree level\" is (leafIndex / 2**height)\n        // \"Left child\" has even index, \"right child\" has odd index\n        if ((leafIndex \u003e\u003e nodeHeight) \u0026 1 == 0) {\n            // Left child\n            return getParent(node, sibling);\n        } else {\n            // Right child\n            return getParent(sibling, node);\n        }\n    }\n\n    /// @notice Calculates the parent of tow nodes in the merkle tree.\n    /// @dev We use implementation with H(0,0) = 0\n    /// This makes EVERY empty node in the tree equal to ZERO,\n    /// saving us from storing H(0,0), H(H(0,0), H(0, 0)), and so on\n    /// @param leftChild    Left child of the calculated node\n    /// @param rightChild   Right child of the calculated node\n    /// @return parent      Value for the node having above mentioned children\n    function getParent(bytes32 leftChild, bytes32 rightChild) internal pure returns (bytes32 parent) {\n        if (leftChild == bytes32(0) \u0026\u0026 rightChild == bytes32(0)) {\n            return 0;\n        } else {\n            return keccak256(bytes.concat(leftChild, rightChild));\n        }\n    }\n\n    // ════════════════════════════════ ROOT/PROOF CALCULATION FOR A LIST OF LEAFS ═════════════════════════════════════\n\n    /**\n     * @notice Calculates merkle root for a list of given leafs.\n     * Merkle Tree is constructed by padding the list with ZERO values for leafs until list length is `2**height`.\n     * Merkle Root is calculated for the constructed tree, and then saved in `leafs[0]`.\n     * \u003e Note:\n     * \u003e - `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * \u003e - Caller is expected not to reuse `hashes` list after the call, and only use `leafs[0]` value,\n     * which is guaranteed to contain the calculated merkle root.\n     * \u003e - root is calculated using the `H(0,0) = 0` Merkle Tree implementation. See MerkleTree.sol for details.\n     * @dev Amount of leaves should be at most `2**height`\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param height    Height of the Merkle Tree to construct\n     */\n    function calculateRoot(bytes32[] memory hashes, uint256 height) internal pure {\n        uint256 levelLength = hashes.length;\n        // Amount of hashes could not exceed amount of leafs in tree with the given height\n        if (levelLength \u003e (1 \u003c\u003c height)) revert TreeHeightTooLow();\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\": the amount of iterations for the for loop above.\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n            }\n        }\n    }\n\n    /**\n     * @notice Generates a proof of inclusion of a leaf in the list. If the requested index is outside\n     * of the list range, generates a proof of inclusion for an empty leaf (proof of non-inclusion).\n     * The Merkle Tree is constructed by padding the list with ZERO values until list length is a power of two\n     * __AND__ index is in the extended list range. For example:\n     *  - `hashes.length == 6` and `0 \u003c= index \u003c= 7` will \"extend\" the list to 8 entries.\n     *  - `hashes.length == 6` and `7 \u003c index \u003c= 15` will \"extend\" the list to 16 entries.\n     * \u003e Note: `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * Caller is expected not to reuse `hashes` list after the call.\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param index     Leaf index to generate the proof for\n     * @return proof    Generated merkle proof\n     */\n    function calculateProof(bytes32[] memory hashes, uint256 index) internal pure returns (bytes32[] memory proof) {\n        // Use only meaningful values for the shortened proof\n        // Check if index is within the list range (we want to generates proofs for outside leafs as well)\n        uint256 height = getHeight(index \u003c hashes.length ? hashes.length : (index + 1));\n        proof = new bytes32[](height);\n        uint256 levelLength = hashes.length;\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Use sibling for the merkle proof; `index^1` is index of our sibling\n                proof[h] = (index ^ 1 \u003c levelLength) ? hashes[index ^ 1] : bytes32(0);\n\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\"\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n                // Traverse to parent node\n                index \u003e\u003e= 1;\n            }\n        }\n    }\n\n    /// @notice Returns the height of the tree having a given amount of leafs.\n    function getHeight(uint256 leafs) internal pure returns (uint256 height) {\n        uint256 amount = 1;\n        while (amount \u003c leafs) {\n            unchecked {\n                ++height;\n            }\n            amount \u003c\u003c= 1;\n        }\n    }\n}\n\n// contracts/libs/stack/GasData.sol\n\n/// GasData in encoded data with \"basic information about gas prices\" for some chain.\ntype GasData is uint96;\n\nusing GasDataLib for GasData global;\n\n/// ChainGas is encoded data with given chain's \"basic information about gas prices\".\ntype ChainGas is uint128;\n\nusing GasDataLib for ChainGas global;\n\n/// Library for encoding and decoding GasData and ChainGas structs.\n/// # GasData\n/// `GasData` is a struct to store the \"basic information about gas prices\", that could\n/// be later used to approximate the cost of a message execution, and thus derive the\n/// minimal tip values for sending a message to the chain.\n/// \u003e - `GasData` is supposed to be cached by `GasOracle` contract, allowing to store the\n/// \u003e approximates instead of the exact values, and thus save on storage costs.\n/// \u003e - For instance, if `GasOracle` only updates the values on +- 10% change, having an\n/// \u003e 0.4% error on the approximates would be acceptable.\n/// `GasData` is supposed to be included in the Origin's state, which are synced across\n/// chains using Agent-signed snapshots and attestations.\n/// ## GasData stack layout (from highest bits to lowest)\n///\n/// | Position   | Field        | Type   | Bytes | Description                                         |\n/// | ---------- | ------------ | ------ | ----- | --------------------------------------------------- |\n/// | (012..010] | gasPrice     | uint16 | 2     | Gas price for the chain (in Wei per gas unit)       |\n/// | (010..008] | dataPrice    | uint16 | 2     | Calldata price (in Wei per byte of content)         |\n/// | (008..006] | execBuffer   | uint16 | 2     | Tx fee safety buffer for message execution (in Wei) |\n/// | (006..004] | amortAttCost | uint16 | 2     | Amortized cost for attestation submission (in Wei)  |\n/// | (004..002] | etherPrice   | uint16 | 2     | Chain's Ether Price / Mainnet Ether Price (in BWAD) |\n/// | (002..000] | markup       | uint16 | 2     | Markup for the message execution (in BWAD)          |\n/// \u003e See Number.sol for more details on `Number` type and BWAD (binary WAD) math.\n///\n/// ## ChainGas stack layout (from highest bits to lowest)\n///\n/// | Position   | Field   | Type   | Bytes | Description      |\n/// | ---------- | ------- | ------ | ----- | ---------------- |\n/// | (016..004] | gasData | uint96 | 12    | Chain's gas data |\n/// | (004..000] | domain  | uint32 | 4     | Chain's domain   |\nlibrary GasDataLib {\n    /// @dev Amount of bits to shift to gasPrice field\n    uint96 private constant SHIFT_GAS_PRICE = 10 * 8;\n    /// @dev Amount of bits to shift to dataPrice field\n    uint96 private constant SHIFT_DATA_PRICE = 8 * 8;\n    /// @dev Amount of bits to shift to execBuffer field\n    uint96 private constant SHIFT_EXEC_BUFFER = 6 * 8;\n    /// @dev Amount of bits to shift to amortAttCost field\n    uint96 private constant SHIFT_AMORT_ATT_COST = 4 * 8;\n    /// @dev Amount of bits to shift to etherPrice field\n    uint96 private constant SHIFT_ETHER_PRICE = 2 * 8;\n\n    /// @dev Amount of bits to shift to gasData field\n    uint128 private constant SHIFT_GAS_DATA = 4 * 8;\n\n    // ═════════════════════════════════════════════════ GAS DATA ══════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded GasData struct with the given fields.\n    /// @param gasPrice_        Gas price for the chain (in Wei per gas unit)\n    /// @param dataPrice_       Calldata price (in Wei per byte of content)\n    /// @param execBuffer_      Tx fee safety buffer for message execution (in Wei)\n    /// @param amortAttCost_    Amortized cost for attestation submission (in Wei)\n    /// @param etherPrice_      Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n    /// @param markup_          Markup for the message execution (in BWAD)\n    function encodeGasData(\n        Number gasPrice_,\n        Number dataPrice_,\n        Number execBuffer_,\n        Number amortAttCost_,\n        Number etherPrice_,\n        Number markup_\n    ) internal pure returns (GasData) {\n        // Number type wraps uint16, so could safely be casted to uint96\n        // forgefmt: disable-next-item\n        return GasData.wrap(\n            uint96(Number.unwrap(gasPrice_)) \u003c\u003c SHIFT_GAS_PRICE |\n            uint96(Number.unwrap(dataPrice_)) \u003c\u003c SHIFT_DATA_PRICE |\n            uint96(Number.unwrap(execBuffer_)) \u003c\u003c SHIFT_EXEC_BUFFER |\n            uint96(Number.unwrap(amortAttCost_)) \u003c\u003c SHIFT_AMORT_ATT_COST |\n            uint96(Number.unwrap(etherPrice_)) \u003c\u003c SHIFT_ETHER_PRICE |\n            uint96(Number.unwrap(markup_))\n        );\n    }\n\n    /// @notice Wraps padded uint256 value into GasData struct.\n    function wrapGasData(uint256 paddedGasData) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(paddedGasData));\n    }\n\n    /// @notice Returns the gas price, in Wei per gas unit.\n    function gasPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_GAS_PRICE));\n    }\n\n    /// @notice Returns the calldata price, in Wei per byte of content.\n    function dataPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_DATA_PRICE));\n    }\n\n    /// @notice Returns the tx fee safety buffer for message execution, in Wei.\n    function execBuffer(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_EXEC_BUFFER));\n    }\n\n    /// @notice Returns the amortized cost for attestation submission, in Wei.\n    function amortAttCost(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_AMORT_ATT_COST));\n    }\n\n    /// @notice Returns the ratio of Chain's Ether Price / Mainnet Ether Price, in BWAD math.\n    function etherPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_ETHER_PRICE));\n    }\n\n    /// @notice Returns the markup for the message execution, in BWAD math.\n    function markup(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data)));\n    }\n\n    // ════════════════════════════════════════════════ CHAIN DATA ═════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded ChainGas struct with the given fields.\n    /// @param gasData_ Chain's gas data\n    /// @param domain_  Chain's domain\n    function encodeChainGas(GasData gasData_, uint32 domain_) internal pure returns (ChainGas) {\n        // GasData type wraps uint96, so could safely be casted to uint128\n        return ChainGas.wrap(uint128(GasData.unwrap(gasData_)) \u003c\u003c SHIFT_GAS_DATA | uint128(domain_));\n    }\n\n    /// @notice Wraps padded uint256 value into ChainGas struct.\n    function wrapChainGas(uint256 paddedChainGas) internal pure returns (ChainGas) {\n        // Casting to uint128 will truncate the highest bits, which is the behavior we want\n        return ChainGas.wrap(uint128(paddedChainGas));\n    }\n\n    /// @notice Returns the chain's gas data.\n    function gasData(ChainGas data) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(ChainGas.unwrap(data) \u003e\u003e SHIFT_GAS_DATA));\n    }\n\n    /// @notice Returns the chain's domain.\n    function domain(ChainGas data) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(ChainGas.unwrap(data));\n    }\n\n    /// @notice Returns the hash for the list of ChainGas structs.\n    function snapGasHash(ChainGas[] memory snapGas) internal pure returns (bytes32 snapGasHash_) {\n        // Use assembly to calculate the hash of the array without copying it\n        // ChainGas takes a single word of storage, thus ChainGas[] is stored in the following way:\n        // 0x00: length of the array, in words\n        // 0x20: first ChainGas struct\n        // 0x40: second ChainGas struct\n        // And so on...\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Find the location where the array data starts, we add 0x20 to skip the length field\n            let loc := add(snapGas, 0x20)\n            // Load the length of the array (in words).\n            // Shifting left 5 bits is equivalent to multiplying by 32: this converts from words to bytes.\n            let len := shl(5, mload(snapGas))\n            // Calculate the hash of the array\n            snapGasHash_ := keccak256(loc, len)\n        }\n    }\n}\n\n// contracts/libs/stack/Header.sol\n\n/// Header is encoded data with \"general routing information\".\ntype Header is uint136;\n\nusing HeaderLib for Header global;\n\n/// Types of messages supported by Origin-Destination\n/// - Base: message sent by protocol user, contains tips\n/// - Manager: message sent between AgentManager contracts located on different chains, no tips\nenum MessageFlag {\n    Base,\n    Manager\n}\n\nusing HeaderLib for MessageFlag global;\n\n/// Library for formatting _the header part_ of _the messages used by Origin and Destination_.\n/// - Header represents general information for routing a Message for Origin and Destination.\n/// - Header occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n///\n/// # Header stack layout (from highest bits to lowest)\n///\n/// | Position   | Field            | Type   | Bytes | Description                             |\n/// | ---------- | ---------------- | ------ | ----- | --------------------------------------- |\n/// | (017..016] | flag             | uint8  | 1     | Flag specifying the type of message     |\n/// | (016..012] | origin           | uint32 | 4     | Domain where message originated         |\n/// | (012..008] | nonce            | uint32 | 4     | Message nonce on the origin domain      |\n/// | (008..004] | destination      | uint32 | 4     | Domain where message will be executed   |\n/// | (004..000] | optimisticPeriod | uint32 | 4     | Optimistic period that will be enforced |\nlibrary HeaderLib {\n    /// @dev Amount of bits to shift to flag field\n    uint136 private constant SHIFT_FLAG = 16 * 8;\n    /// @dev Amount of bits to shift to origin field\n    uint136 private constant SHIFT_ORIGIN = 12 * 8;\n    /// @dev Amount of bits to shift to nonce field\n    uint136 private constant SHIFT_NONCE = 8 * 8;\n    /// @dev Amount of bits to shift to destination field\n    uint136 private constant SHIFT_DESTINATION = 4 * 8;\n\n    /// @notice Returns an encoded header with provided fields\n    /// @param origin_              Domain of origin chain\n    /// @param nonce_               Message nonce on origin chain\n    /// @param destination_         Domain of destination chain\n    /// @param optimisticPeriod_    Optimistic period for message execution\n    function encodeHeader(\n        MessageFlag flag_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint32 destination_,\n        uint32 optimisticPeriod_\n    ) internal pure returns (Header) {\n        // All casts below are upcasts, so they are safe\n        // forgefmt: disable-next-item\n        return Header.wrap(\n            uint136(uint8(flag_)) \u003c\u003c SHIFT_FLAG |\n            uint136(origin_) \u003c\u003c SHIFT_ORIGIN |\n            uint136(nonce_) \u003c\u003c SHIFT_NONCE |\n            uint136(destination_) \u003c\u003c SHIFT_DESTINATION |\n            uint136(optimisticPeriod_)\n        );\n    }\n\n    /// @notice Checks that the header is a valid encoded header.\n    function isHeader(uint256 paddedHeader) internal pure returns (bool) {\n        // Check that flag is within range\n        return _flag(paddedHeader) \u003c= uint8(type(MessageFlag).max);\n    }\n\n    /// @notice Wraps the padded encoded request into a Header-typed value.\n    /// @dev The \"padded\" header is simply an encoded header casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded headers\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedHeader) internal pure returns (Header) {\n        // Check that flag is within range\n        if (!isHeader(paddedHeader)) revert FlagOutOfRange();\n        // Casting to uint136 will truncate the highest bits, which is the behavior we want\n        return Header.wrap(uint136(paddedHeader));\n    }\n\n    /// @notice Returns header's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Header header) internal pure returns (bytes32 hashedHeader) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store header in scratch space\n            mstore(0, header)\n            // Compute hash of header padded to 32 bytes\n            hashedHeader := keccak256(0, 32)\n        }\n    }\n\n    // ══════════════════════════════════════════════ HEADER SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns header's flag field\n    function flag(Header header) internal pure returns (MessageFlag) {\n        // We check that flag is within range when wrapping the header, so this cast is safe\n        return MessageFlag(_flag(Header.unwrap(header)));\n    }\n\n    /// @notice Returns header's origin field\n    function origin(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_ORIGIN);\n    }\n\n    /// @notice Returns header's nonce field\n    function nonce(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_NONCE);\n    }\n\n    /// @notice Returns header's destination field\n    function destination(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_DESTINATION);\n    }\n\n    /// @notice Returns header's optimistic seconds field\n    function optimisticPeriod(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns header's flag field without casting to MessageFlag\n    function _flag(uint256 paddedHeader) private pure returns (uint8) {\n        // Casting to uint8 will truncate the highest bits, which is the behavior we want\n        return uint8(paddedHeader \u003e\u003e SHIFT_FLAG);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n     * constructor.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall \u0026\u0026 _initialized \u003c 1) || (!AddressUpgradeable.isContract(address(this)) \u0026\u0026 _initialized == 1),\n            \"Initializable: contract is already initialized\"\n        );\n        _initialized = 1;\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: setting the version to 255 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing \u0026\u0026 _initialized \u003c version, \"Initializable: contract is already initialized\");\n        _initialized = version;\n        _initializing = true;\n        _;\n        _initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        require(_initializing, \"Initializable: contract is not initializing\");\n        _;\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized != type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint8) {\n        return _initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _initializing;\n    }\n}\n\n// contracts/interfaces/IAgentManager.sol\n\ninterface IAgentManager {\n    /**\n     * @notice Allows Inbox to open a Dispute between a Guard and a Notary, if they are both not in Dispute already.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Guard or Notary is already in Dispute.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Allows Inbox to slash an agent, if their fraud was proven.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Domain doesn't match the saved agent domain.\n     * @param domain    Domain where the Agent is active\n     * @param agent     Address of the Agent\n     * @param prover    Address that initially provided fraud proof\n     */\n    function slashAgent(uint32 domain, address agent, address prover) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest known root of the Agent Merkle Tree.\n     */\n    function agentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns the number of opened Disputes.\n     * @dev This includes the Disputes that have been resolved already.\n     */\n    function getDisputesAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns information about the dispute with the given index.\n     * @dev Will revert if dispute with given index hasn't been opened yet.\n     * @param index             Dispute index\n     * @return guard            Address of the Guard in the Dispute\n     * @return notary           Address of the Notary in the Dispute\n     * @return slashedAgent     Address of the Agent who was slashed when Dispute was resolved\n     * @return fraudProver      Address who provided fraud proof to resolve the Dispute\n     * @return reportPayload    Raw payload with report data that led to the Dispute\n     * @return reportSignature  Guard signature for the report payload\n     */\n    function getDispute(uint256 index)\n        external\n        view\n        returns (\n            address guard,\n            address notary,\n            address slashedAgent,\n            address fraudProver,\n            bytes memory reportPayload,\n            bytes memory reportSignature\n        );\n\n    /**\n     * @notice Returns the current Dispute status of a given agent. See Structures.sol for details.\n     * @dev Every returned value will be set to zero if agent was not slashed and is not in Dispute.\n     * `rival` and `disputePtr` will be set to zero if the agent was slashed without being in Dispute.\n     * @param agent         Agent address\n     * @return flag         Flag describing the current Dispute status for the agent: None/Pending/Slashed\n     * @return rival        Address of the rival agent in the Dispute\n     * @return fraudProver  Address who provided fraud proof to resolve the Dispute\n     * @return disputePtr   Index of the opened Dispute PLUS ONE. Zero if agent is not in Dispute.\n     */\n    function disputeStatus(address agent)\n        external\n        view\n        returns (DisputeFlag flag, address rival, address fraudProver, uint256 disputePtr);\n}\n\n// contracts/interfaces/IAgentSecured.sol\n\ninterface IAgentSecured {\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * between a Guard and a Notary has been opened.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * has been resolved due to one of the agents being slashed.\n     * \u003e `rivalIndex` will be ZERO, if the slashed agent was not in the Dispute.\n     * @param slashedIndex  Index of the slashed agent in the Agent Merkle Tree\n     * @param rivalIndex    Index of the their Dispute Rival in the Agent Merkle Tree\n     */\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the address of the local AgentManager contract, which is treated as\n     * the \"source of truth\" for agent statuses.\n     */\n    function agentManager() external view returns (address);\n\n    /**\n     * @notice Returns the address of the local Inbox contract, which is treated as\n     * the \"source of truth\" for agent-signed statements.\n     * @dev Inbox passes verified agent statements to `IAgentSecured` contract.\n     */\n    function inbox() external view returns (address);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns (flag, openedAt, resolvedAt) that describes the latest status of\n     * the latest dispute for an agent with a given index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param agentIndex    Agent index in the Agent Merkle Tree\n     * @return              Latest dispute status for the given agent: (flag, openedAt, resolvedAt)\n     */\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory);\n}\n\n// contracts/libs/memory/ByteString.sol\n\n/// @dev CallData is a memory view over the payload to be used for an external call, i.e.\n/// recipient.call(callData). Its length is always (4 + 32 * N) bytes:\n/// - First 4 bytes represent the function selector.\n/// - 32 * N bytes represent N words that function arguments occupy.\ntype CallData is uint256;\n\n/// @dev Attach library functions to CallData\nusing ByteString for CallData global;\n\n/// @dev Signature is a memory view over a \"65 bytes\" array representing a ECDSA signature.\ntype Signature is uint256;\n\n/// @dev Attach library functions to Signature\nusing ByteString for Signature global;\n\nlibrary ByteString {\n    using MemViewLib for bytes;\n\n    /**\n     * @dev non-compact ECDSA signatures are enforced as of OZ 4.7.3\n     *\n     *      Signature payload memory layout\n     * [000 .. 032) r   bytes32 32 bytes\n     * [032 .. 064) s   bytes32 32 bytes\n     * [064 .. 065) v   uint8    1 byte\n     */\n    uint256 internal constant SIGNATURE_LENGTH = 65;\n    uint256 private constant OFFSET_R = 0;\n    uint256 private constant OFFSET_S = 32;\n    uint256 private constant OFFSET_V = 64;\n\n    /**\n     * @dev Calldata memory layout\n     * [000 .. 004) selector    bytes4  4 bytes\n     *      Optional: N function arguments\n     * [004 .. 036) arg1        bytes32 32 bytes\n     *      ..\n     * [AAA .. END) argN        bytes32 32 bytes\n     */\n    uint256 internal constant SELECTOR_LENGTH = 4;\n    uint256 private constant OFFSET_SELECTOR = 0;\n    uint256 private constant OFFSET_ARGUMENTS = SELECTOR_LENGTH;\n\n    // ═════════════════════════════════════════════════ SIGNATURE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the signature payload from the given values.\n     * @dev Using ByteString.formatSignature({r: r, s: s, v: v}) will make sure\n     * that params are given in the right order.\n     */\n    function formatSignature(bytes32 r, bytes32 s, uint8 v) internal pure returns (bytes memory) {\n        return abi.encodePacked(r, s, v);\n    }\n\n    /**\n     * @notice Returns a Signature view over for the given payload.\n     * @dev Will revert if the payload is not a signature.\n     */\n    function castToSignature(bytes memory payload) internal pure returns (Signature) {\n        return castToSignature(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Signature view.\n     * @dev Will revert if the memory view is not over a signature.\n     */\n    function castToSignature(MemView memView) internal pure returns (Signature) {\n        if (!isSignature(memView)) revert UnformattedSignature();\n        return Signature.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a signature\n     */\n    function isSignature(MemView memView) internal pure returns (bool) {\n        return memView.len() == SIGNATURE_LENGTH;\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Signature signature) internal pure returns (MemView) {\n        return MemView.wrap(Signature.unwrap(signature));\n    }\n\n    // ═════════════════════════════════════════════ SIGNATURE SLICING ═════════════════════════════════════════════════\n\n    /// @notice Unpacks signature payload into (r, s, v) parameters.\n    /// @dev Make sure to verify signature length with isSignature() beforehand.\n    function toRSV(Signature signature) internal pure returns (bytes32 r, bytes32 s, uint8 v) {\n        // Get the underlying memory view\n        MemView memView = unwrap(signature);\n        r = memView.index({index_: OFFSET_R, bytes_: 32});\n        s = memView.index({index_: OFFSET_S, bytes_: 32});\n        // Can be safely casted to uint8, since we index a single byte\n        v = uint8(memView.indexUint({index_: OFFSET_V, bytes_: 1}));\n    }\n\n    // ═════════════════════════════════════════════════ CALLDATA ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the calldata with the modified arguments:\n     * the existing arguments are prepended with the arguments from the prefix.\n     * @dev Given:\n     *  - `calldata = abi.encodeWithSelector(foo.selector, d, e);`\n     *  - `prefix = abi.encode(a, b, c);`\n     *  - `a`, `b`, `c` are arguments of static type (i.e. not dynamically sized ones)\n     *      Then:\n     *  - Function will return abi.encodeWithSelector(foo.selector, a, c, c, d, e)\n     *  - Returned calldata will trigger `foo(a, b, c, d, e)` when used for a contract call.\n     * Note: for clarification as to what types are considered static, see\n     * https://docs.soliditylang.org/en/latest/abi-spec.html#formal-specification-of-the-encoding\n     * @param callData  Calldata that needs to be modified\n     * @param prefix    ABI-encoded arguments to use as the first arguments in the new calldata\n     * @return Modified calldata having prefix as the first arguments.\n     */\n    function addPrefix(CallData callData, bytes memory prefix) internal view returns (bytes memory) {\n        // Prefix should occupy a whole amount of words in memory\n        if (!_fullWords(prefix.length)) revert UnformattedCallDataPrefix();\n        MemView[] memory views = new MemView[](3);\n        // Use payload's function selector\n        views[0] = abi.encodePacked(callData.callSelector()).ref();\n        // Use prefix as the first arguments\n        views[1] = prefix.ref();\n        // Use payload's remaining arguments\n        views[2] = callData.arguments();\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a CallData view over for the given payload.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(bytes memory payload) internal pure returns (CallData) {\n        return castToCallData(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a CallData view.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(MemView memView) internal pure returns (CallData) {\n        if (!isCallData(memView)) revert UnformattedCallData();\n        return CallData.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a valid calldata, i.e.\n     * a function selector, followed by arbitrary amount of arguments.\n     */\n    function isCallData(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Calldata should at least have a function selector\n        if (length \u003c SELECTOR_LENGTH) return false;\n        // The remainder of the calldata should be exactly N memory words (N \u003e= 0)\n        return _fullWords(length - SELECTOR_LENGTH);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(CallData callData) internal pure returns (MemView) {\n        return MemView.wrap(CallData.unwrap(callData));\n    }\n\n    /// @notice Returns callData's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(CallData callData) internal pure returns (bytes32) {\n        return callData.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ CALLDATA SLICING ══════════════════════════════════════════════════\n\n    /**\n     * @notice Returns amount of memory words (32 byte chunks) the function arguments\n     * occupy in the calldata.\n     * @dev This might differ from amount of arguments supplied, if any of the arguments\n     * occupies more than one memory slot. It is true, however, that argument part of the payload\n     * occupies exactly N words, even for dynamic types like `bytes`\n     */\n    function argumentWords(CallData callData) internal pure returns (uint256) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        // Equivalent of (length - SELECTOR_LENGTH) / 32\n        return (memView.len() - SELECTOR_LENGTH) \u003e\u003e 5;\n    }\n\n    /// @notice Returns selector for the provided calldata.\n    function callSelector(CallData callData) internal pure returns (bytes4) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return bytes4(memView.index({index_: OFFSET_SELECTOR, bytes_: SELECTOR_LENGTH}));\n    }\n\n    /// @notice Returns abi encoded arguments for the provided calldata.\n    function arguments(CallData callData) internal pure returns (MemView) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return memView.sliceFrom({index_: OFFSET_ARGUMENTS});\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if length is full amount of memory words (32 bytes).\n    function _fullWords(uint256 length) internal pure returns (bool) {\n        // The equivalent of length % 32 == 0\n        return length \u0026 31 == 0;\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n    function __Context_init() internal onlyInitializing {\n    }\n\n    function __Context_init_unchained() internal onlyInitializing {\n    }\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[50] private __gap;\n}\n\n// contracts/libs/merkle/MerkleTree.sol\n\n/// `BaseTree` is a struct representing incremental merkle tree.\n/// - Contains only the current branch.\n/// - The number of inserted leaves is stored externally, and is later supplied for tree operations.\n/// - Has a fixed height of `ORIGIN_TREE_HEIGHT`.\n/// - Can store up to `2 ** ORIGIN_TREE_HEIGHT - 1` leaves.\n/// \u003e Note: the hash function for the tree `H(x, y)` is defined as:\n/// \u003e - `H(0,0) = 0`\n/// \u003e - `H(x,y) = keccak256(x, y), when (x != 0 || y != 0)`\n/// ## Invariant for leafs\n/// - The leftmost empty leaf has `index == count`, where `count` is the amount of the inserted leafs so far.\n/// - Value for any empty leaf or node is bytes32(0).\n/// ## Invariant for current branch\n/// `branch[i]` is always the value of a node on the i-th level.\n/// Levels are numbered from leafs to root: `0 .. ORIGIN_TREE_HEIGHT`.\n/// `branch[i]` stores the value for the node, such that:\n//  - The node is a \"left child\" (e.g. has an even index).\n/// - The node must have two non-empty children.\n/// - Out of all level's \"left child\" nodes with \"non-empty children\",\n/// the one with the biggest index (the rightmost one) is stored as `branch[i]`.\n/// \u003e __`branch` could be used to form a proof of inclusion for the first empty leaf (`index == count`).__\n/// _Here is how:_\n/// - Let's walk along the path from the \"first empty leaf\" to the root.\n/// - i-th bit of the \"first empty leaf\" index (which is equal to `count`) determines if the path's node\n/// for this i-th level is a \"left child\" or a \"right child\".\n/// - i-th bit in `count` is 0 → we are the left child on this level → sibling is the right child\n/// that does not exist yet → `proof[i] = bytes32(0)`.\n/// - i-th bit in `count` is 1 → we are the right child on this level → sibling is the left child\n/// sibling is the rightmost \"left child\" node on the level → `proof[i] = branch[i]`.\n/// \u003e Therefore `proof[i] = (count \u0026 (1 \u003c\u003c i)) == 0 ? bytes32(0) : branch[i])`\nstruct BaseTree {\n    bytes32[ORIGIN_TREE_HEIGHT] branch;\n}\n\nusing MerkleTree for BaseTree global;\n\n/// `HistoricalTree` is an incremental merkle tree keeping track of its historical merkle roots.\n/// \u003e - `roots[N]` is the root of the tree after `N` leafs were inserted\n/// \u003e - `roots[0] == bytes32(0)`\n/// @param tree     Incremental merkle tree\n/// @param roots    Historical merkle roots of the tree\nstruct HistoricalTree {\n    BaseTree tree;\n    bytes32[] roots;\n}\n\nusing MerkleTree for HistoricalTree global;\n\n/// `DynamicTree` is a struct representing a Merkle Tree with `2**AGENT_TREE_HEIGHT` leaves.\n/// - A single operation is available: update value for leaf with an arbitrary index (which might be a non-empty leaf).\n/// - This is done by requesting the proof of inclusion for the old value, which is used to both\n/// verify the old value, and calculate the new root.\n/// \u003e Based on Original idea from [ER forum post](https://ethresear.ch/t/efficient-on-chain-dynamic-merkle-tree/11054).\nstruct DynamicTree {\n    bytes32 root;\n}\n\nusing MerkleTree for DynamicTree global;\n\n/// MerkleTree is work based on Nomad's Merkle.sol, which is used under MIT OR Apache-2.0\n/// [link](https://github.com/nomad-xyz/monorepo/blob/main/packages/contracts-core/contracts/libs/Merkle.sol).\n/// With the following changes:\n/// - Adapted for Solidity 0.8.x.\n/// - Amount of tree leaves stored externally.\n/// - Added thorough documentation.\n/// - `H(0,0) = 0` optimization from [ER forum post](https://ethresear.ch/t/optimizing-sparse-merkle-trees/3751/6).\n/// \u003e Nomad's Merkle.sol is work based on eth2 deposit contract, which is used under CC0-1.0\n///[link](https://github.com/ethereum/deposit_contract/blob/dev/deposit_contract/contracts/validator_registration.v.py).\n/// With the following changes:\n/// \u003e - Implemented in Solidity 0.7.6 (eth2 deposit contract implemented in Vyper).\n/// \u003e - `H() = keccak256()` is used as the hashing function instead of `sha256()`.\nlibrary MerkleTree {\n    /// @dev For root calculation we need at least one empty leaf, thus the minus one in the formula.\n    uint256 internal constant MAX_LEAVES = 2 ** ORIGIN_TREE_HEIGHT - 1;\n\n    // ═════════════════════════════════════════════════ BASE TREE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Inserts `node` into merkle tree\n     * @dev Reverts if tree is full\n     * @param newCount  Amount of inserted leaves in the tree after the insertion (i.e. current + 1)\n     * @param node      Element to insert into tree\n     */\n    function insertBase(BaseTree storage tree, uint256 newCount, bytes32 node) internal {\n        if (newCount \u003e MAX_LEAVES) revert MerkleTreeFull();\n        // We go up the tree following the branch from the empty leaf AFTER the just inserted one.\n        // We stop when we find the first \"right child\" node.\n        // Its sibling is now the rightmost \"left child\" node that has two non-empty children.\n        // Therefore we need to update `tree.branch` value on this level.\n        // One could see that `tree.branch` value on lower and higher levels remain unchanged.\n\n        // Loop invariant: `node` is the current level's value for the branch from JUST INSERTED leaf\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            if ((newCount \u0026 1) == 1) {\n                // Found the first \"right child\" node on the branch from EMPTY leaf\n                // `node` is the value for node on branch from JUST INSERTED leaf\n                // Which in this case is the \"left child\".\n                // We update tree.branch and exit\n                tree.branch[i] = node;\n                return;\n            }\n            // On the branch from EMPTY leaf this is still a \"left child\".\n            // Meaning on branch from JUST INSERTED leaf, `node` is a right child.\n            // We compute value for `node` parent using `tree.branch` invariant:\n            // This is the rightmost \"left child\" node, which would be sibling of `node`.\n            node = MerkleMath.getParent(tree.branch[i], node);\n            // Get the parent index, and go to the next tree level\n            newCount \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n        // As the loop should always end prematurely with the `return` statement,\n        // this code should be unreachable. We assert `false` just to be safe.\n        assert(false);\n    }\n\n    /**\n     * @notice Calculates and returns current root of the merkle tree.\n     * @param count     Current amount of inserted leaves in the tree\n     * @return current  Calculated root of `tree`\n     */\n    function rootBase(BaseTree storage tree, uint256 count) internal view returns (bytes32 current) {\n        // To calculate the root we follow the branch of first EMPTY leaf (index == count)\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            // Check if we are the left or the right child on the current level\n            if ((count \u0026 1) == 1) {\n                // We are the right child. Our sibling is the \"rightmost\" \"left-child\" node\n                // that has two non-empty children → sibling is `tree.branch[i]`\n                current = MerkleMath.getParent(tree.branch[i], current);\n            } else {\n                // We are the left child. Our sibling does not exist yet → sibling is EMPTY\n                current = MerkleMath.getParent(current, bytes32(0));\n            }\n            // Get the parent index, and go to the next tree level\n            count \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    // ══════════════════════════════════════════════ HISTORICAL TREE ══════════════════════════════════════════════════\n\n    /// @notice Initializes the historical roots for the tree by inserting an empty root.\n    // solhint-disable-next-line ordering\n    function initializeRoots(HistoricalTree storage tree) internal returns (bytes32 savedRoot) {\n        // This should only be called once, when the contract is initialized\n        assert(tree.roots.length == 0);\n        // Save root for empty merkle tree: bytes32(0)\n        tree.roots.push(savedRoot);\n    }\n\n    /// @notice Inserts a new leaf into the merkle tree.\n    /// @dev Reverts if tree is full.\n    /// @param node         Element to insert into tree\n    /// @return newRoot     Merkle root after the leaf was inserted\n    function insert(HistoricalTree storage tree, bytes32 node) internal returns (bytes32 newRoot) {\n        // Tree count after the new leaf will be inserted (we store roots[0] as root of empty tree)\n        uint256 newCount = tree.roots.length;\n        tree.tree.insertBase(newCount, node);\n        // Save the new root\n        newRoot = tree.tree.rootBase(newCount);\n        tree.roots.push(newRoot);\n    }\n\n    /// @notice Returns the historical root of the merkle tree.\n    /// @dev Reverts if not enough leafs have been inserted.\n    /// @param count            Amount of leafs in the tree at some point of time\n    /// @return historicalRoot  Merkle root after `count` leafs were inserted\n    function root(HistoricalTree storage tree, uint256 count) internal view returns (bytes32 historicalRoot) {\n        if (count \u003e= tree.roots.length) revert NotEnoughLeafs();\n        return tree.roots[count];\n    }\n\n    // ═══════════════════════════════════════════════ DYNAMIC TREE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Updates the value for the leaf with the given index in the Dynamic Merkle Tree.\n     * @dev Will revert if incorrect proof of inclusion for old value is supplied.\n     * @param tree          Dynamic merkle tree\n     * @param index         Index of the leaf to update\n     * @param oldValue      Previous value of the leaf\n     * @param branch        Proof of inclusion of previous value into the tree\n     * @param newValue      New leaf value to assign\n     * @return newRoot      New value for the Merkle Root after the leaf is updated\n     */\n    function update(\n        DynamicTree storage tree,\n        uint256 index,\n        bytes32 oldValue,\n        bytes32[] memory branch,\n        bytes32 newValue\n    ) internal returns (bytes32 newRoot) {\n        // Check that the old value + proof result in a correct root\n        if (MerkleMath.proofRoot(index, oldValue, branch, AGENT_TREE_HEIGHT) != tree.root) {\n            revert LeafNotProven();\n        }\n        // New root is new value + the same proof (values for sibling nodes are not updated)\n        newRoot = MerkleMath.proofRoot(index, newValue, branch, AGENT_TREE_HEIGHT);\n        // Write the new root\n        tree.root = newRoot;\n    }\n}\n\n// contracts/libs/stack/Tips.sol\n\n/// Tips is encoded data with \"tips paid for sending a base message\".\n/// Note: even though uint256 is also an underlying type for MemView, Tips is stored ON STACK.\ntype Tips is uint256;\n\nusing TipsLib for Tips global;\n\n/// # Tips\n/// Library for formatting _the tips part_ of _the base messages_.\n///\n/// ## How the tips are awarded\n/// Tips are paid for sending a base message, and are split across all the agents that\n/// made the message execution on destination chain possible.\n/// ### Summit tips\n/// Split between:\n///     - Guard posting a snapshot with state ST_G for the origin chain.\n///     - Notary posting a snapshot SN_N using ST_G. This creates attestation A.\n///     - Notary posting a message receipt after it is executed on destination chain.\n/// ### Attestation tips\n/// Paid to:\n///     - Notary posting attestation A to destination chain.\n/// ### Execution tips\n/// Paid to:\n///     - First executor performing a valid execution attempt (correct proofs, optimistic period over),\n///      using attestation A to prove message inclusion on origin chain, whether the recipient reverted or not.\n/// ### Delivery tips.\n/// Paid to:\n///     - Executor who successfully executed the message on destination chain.\n///\n/// ## Tips encoding\n/// - Tips occupy a single storage word, and thus are stored on stack instead of being stored in memory.\n/// - The actual tip values should be determined by multiplying stored values by divided by TIPS_MULTIPLIER=2**32.\n/// - Tips are packed into a single word of storage, while allowing real values up to ~8*10**28 for every tip category.\n/// \u003e The only downside is that the \"real tip values\" are now multiplies of ~4*10**9, which should be fine even for\n/// the chains with the most expensive gas currency.\n/// # Tips stack layout (from highest bits to lowest)\n///\n/// | Position   | Field          | Type   | Bytes | Description                                                |\n/// | ---------- | -------------- | ------ | ----- | ---------------------------------------------------------- |\n/// | (032..024] | summitTip      | uint64 | 8     | Tip for agents interacting with Summit contract            |\n/// | (024..016] | attestationTip | uint64 | 8     | Tip for Notary posting attestation to Destination contract |\n/// | (016..008] | executionTip   | uint64 | 8     | Tip for valid execution attempt on destination chain       |\n/// | (008..000] | deliveryTip    | uint64 | 8     | Tip for successful message delivery on destination chain   |\n\nlibrary TipsLib {\n    using SafeCast for uint256;\n\n    /// @dev Amount of bits to shift to summitTip field\n    uint256 private constant SHIFT_SUMMIT_TIP = 24 * 8;\n    /// @dev Amount of bits to shift to attestationTip field\n    uint256 private constant SHIFT_ATTESTATION_TIP = 16 * 8;\n    /// @dev Amount of bits to shift to executionTip field\n    uint256 private constant SHIFT_EXECUTION_TIP = 8 * 8;\n\n    // ═══════════════════════════════════════════════════ TIPS ════════════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips with the given fields\n    /// @param summitTip_        Tip for agents interacting with Summit contract, divided by TIPS_MULTIPLIER\n    /// @param attestationTip_   Tip for Notary posting attestation to Destination contract, divided by TIPS_MULTIPLIER\n    /// @param executionTip_     Tip for valid execution attempt on destination chain, divided by TIPS_MULTIPLIER\n    /// @param deliveryTip_      Tip for successful message delivery on destination chain, divided by TIPS_MULTIPLIER\n    function encodeTips(uint64 summitTip_, uint64 attestationTip_, uint64 executionTip_, uint64 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // forgefmt: disable-next-item\n        return Tips.wrap(\n            uint256(summitTip_) \u003c\u003c SHIFT_SUMMIT_TIP |\n            uint256(attestationTip_) \u003c\u003c SHIFT_ATTESTATION_TIP |\n            uint256(executionTip_) \u003c\u003c SHIFT_EXECUTION_TIP |\n            uint256(deliveryTip_)\n        );\n    }\n\n    /// @notice Convenience function to encode tips with uint256 values.\n    function encodeTips256(uint256 summitTip_, uint256 attestationTip_, uint256 executionTip_, uint256 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // In practice, the tips amounts are not supposed to be higher than 2**96, and with 32 bits of granularity\n        // using uint64 is enough to store the values. However, we still check for overflow just in case.\n        // TODO: consider using Number type to store the tips values.\n        return encodeTips({\n            summitTip_: (summitTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            attestationTip_: (attestationTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            executionTip_: (executionTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            deliveryTip_: (deliveryTip_ \u003e\u003e TIPS_GRANULARITY).toUint64()\n        });\n    }\n\n    /// @notice Wraps the padded encoded tips into a Tips-typed value.\n    /// @dev There is no actual padding here, as the underlying type is already uint256,\n    /// but we include this function for consistency and to be future-proof, if tips will eventually use anything\n    /// smaller than uint256.\n    function wrapPadded(uint256 paddedTips) internal pure returns (Tips) {\n        return Tips.wrap(paddedTips);\n    }\n\n    /**\n     * @notice Returns a formatted Tips payload specifying empty tips.\n     * @return Formatted tips\n     */\n    function emptyTips() internal pure returns (Tips) {\n        return Tips.wrap(0);\n    }\n\n    /// @notice Returns tips's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Tips tips) internal pure returns (bytes32 hashedTips) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store tips in scratch space\n            mstore(0, tips)\n            // Compute hash of tips padded to 32 bytes\n            hashedTips := keccak256(0, 32)\n        }\n    }\n\n    // ═══════════════════════════════════════════════ TIPS SLICING ════════════════════════════════════════════════════\n\n    /// @notice Returns summitTip field\n    function summitTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_SUMMIT_TIP);\n    }\n\n    /// @notice Returns attestationTip field\n    function attestationTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_ATTESTATION_TIP);\n    }\n\n    /// @notice Returns executionTip field\n    function executionTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_EXECUTION_TIP);\n    }\n\n    /// @notice Returns deliveryTip field\n    function deliveryTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips));\n    }\n\n    // ════════════════════════════════════════════════ TIPS VALUE ═════════════════════════════════════════════════════\n\n    /// @notice Returns total value of the tips payload.\n    /// This is the sum of the encoded values, scaled up by TIPS_MULTIPLIER\n    function value(Tips tips) internal pure returns (uint256 value_) {\n        value_ = uint256(tips.summitTip()) + tips.attestationTip() + tips.executionTip() + tips.deliveryTip();\n        value_ \u003c\u003c= TIPS_GRANULARITY;\n    }\n\n    /// @notice Increases the delivery tip to match the new value.\n    function matchValue(Tips tips, uint256 newValue) internal pure returns (Tips newTips) {\n        uint256 oldValue = tips.value();\n        if (newValue \u003c oldValue) revert TipsValueTooLow();\n        // We want to increase the delivery tip, while keeping the other tips the same\n        unchecked {\n            uint256 delta = (newValue - oldValue) \u003e\u003e TIPS_GRANULARITY;\n            // `delta` fits into uint224, as TIPS_GRANULARITY is 32, so this never overflows uint256.\n            // In practice, this will never overflow uint64 as well, but we still check it just in case.\n            if (delta + tips.deliveryTip() \u003e type(uint64).max) revert TipsOverflow();\n            // Delivery tips occupy lowest 8 bytes, so we can just add delta to the tips value\n            // to effectively increase the delivery tip (knowing that delta fits into uint64).\n            newTips = Tips.wrap(Tips.unwrap(tips) + delta);\n        }\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    function __Ownable_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable_init_unchained() internal onlyInitializing {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n    function __Ownable2Step_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable2Step_init_unchained() internal onlyInitializing {\n    }\n    address private _pendingOwner;\n\n    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Returns the address of the pending owner.\n     */\n    function pendingOwner() public view virtual returns (address) {\n        return _pendingOwner;\n    }\n\n    /**\n     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual override onlyOwner {\n        _pendingOwner = newOwner;\n        emit OwnershipTransferStarted(owner(), newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual override {\n        delete _pendingOwner;\n        super._transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev The new owner accepts the ownership transfer.\n     */\n    function acceptOwnership() public virtual {\n        address sender = _msgSender();\n        require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n        _transferOwnership(sender);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// contracts/libs/memory/State.sol\n\n/// State is a memory view over a formatted state payload.\ntype State is uint256;\n\nusing StateLib for State global;\n\n/// # State\n/// State structure represents the state of Origin contract at some point of time.\n/// - State is structured in a way to track the updates of the Origin Merkle Tree.\n/// - State includes root of the Origin Merkle Tree, origin domain and some additional metadata.\n/// ## Origin Merkle Tree\n/// Hash of every sent message is inserted in the Origin Merkle Tree, which changes\n/// the value of Origin Merkle Root (which is the root for the mentioned tree).\n/// - Origin has a single Merkle Tree for all messages, regardless of their destination domain.\n/// - This leads to Origin state being updated if and only if a message was sent in a block.\n/// - Origin contract is a \"source of truth\" for states: a state is considered \"valid\" in its Origin,\n/// if it matches the state of the Origin contract after the N-th (nonce) message was sent.\n///\n/// # Memory layout of State fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                    |\n/// | ---------- | ----------- | ------- | ----- | ------------------------------ |\n/// | [000..032) | root        | bytes32 | 32    | Root of the Origin Merkle Tree |\n/// | [032..036) | origin      | uint32  | 4     | Domain where Origin is located |\n/// | [036..040) | nonce       | uint32  | 4     | Amount of sent messages        |\n/// | [040..045) | blockNumber | uint40  | 5     | Block of last sent message     |\n/// | [045..050) | timestamp   | uint40  | 5     | Time of last sent message      |\n/// | [050..062) | gasData     | uint96  | 12    | Gas data for the chain         |\n///\n/// @dev State could be used to form a Snapshot to be signed by a Guard or a Notary.\nlibrary StateLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_ROOT = 0;\n    uint256 private constant OFFSET_ORIGIN = 32;\n    uint256 private constant OFFSET_NONCE = 36;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 40;\n    uint256 private constant OFFSET_TIMESTAMP = 45;\n    uint256 private constant OFFSET_GAS_DATA = 50;\n\n    // ═══════════════════════════════════════════════════ STATE ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted State payload with provided fields\n     * @param root_         New merkle root\n     * @param origin_       Domain of Origin's chain\n     * @param nonce_        Nonce of the merkle root\n     * @param blockNumber_  Block number when root was saved in Origin\n     * @param timestamp_    Block timestamp when root was saved in Origin\n     * @param gasData_      Gas data for the chain\n     * @return Formatted state\n     */\n    function formatState(\n        bytes32 root_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_,\n        GasData gasData_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(root_, origin_, nonce_, blockNumber_, timestamp_, gasData_);\n    }\n\n    /**\n     * @notice Returns a State view over the given payload.\n     * @dev Will revert if the payload is not a state.\n     */\n    function castToState(bytes memory payload) internal pure returns (State) {\n        return castToState(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a State view.\n     * @dev Will revert if the memory view is not over a state.\n     */\n    function castToState(MemView memView) internal pure returns (State) {\n        if (!isState(memView)) revert UnformattedState();\n        return State.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted State.\n    function isState(MemView memView) internal pure returns (bool) {\n        return memView.len() == STATE_LENGTH;\n    }\n\n    /// @notice Returns the hash of a State, that could be later signed by a Guard to signal\n    /// that the state is invalid.\n    function hashInvalid(State state) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(stateInvalidSalt, keccak(state))\n        return state.unwrap().keccakSalted(STATE_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(State state) internal pure returns (MemView) {\n        return MemView.wrap(State.unwrap(state));\n    }\n\n    /// @notice Compares two State structures.\n    function equals(State a, State b) internal pure returns (bool) {\n        // Length of a State payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═══════════════════════════════════════════════ STATE HASHING ═══════════════════════════════════════════════════\n\n    /// @notice Returns the hash of the State.\n    /// @dev We are using the Merkle Root of a tree with two leafs (see below) as state hash.\n    function leaf(State state) internal pure returns (bytes32) {\n        (bytes32 leftLeaf_, bytes32 rightLeaf_) = state.subLeafs();\n        // Final hash is the parent of these leafs\n        return keccak256(bytes.concat(leftLeaf_, rightLeaf_));\n    }\n\n    /// @notice Returns \"sub-leafs\" of the State. Hash of these \"sub leafs\" is going to be used\n    /// as a \"state leaf\" in the \"Snapshot Merkle Tree\".\n    /// This enables proving that leftLeaf = (root, origin) was a part of the \"Snapshot Merkle Tree\",\n    /// by combining `rightLeaf` with the remainder of the \"Snapshot Merkle Proof\".\n    function subLeafs(State state) internal pure returns (bytes32 leftLeaf_, bytes32 rightLeaf_) {\n        MemView memView = state.unwrap();\n        // Left leaf is (root, origin)\n        leftLeaf_ = memView.prefix({len_: OFFSET_NONCE}).keccak();\n        // Right leaf is (metadata), or (nonce, blockNumber, timestamp)\n        rightLeaf_ = memView.sliceFrom({index_: OFFSET_NONCE}).keccak();\n    }\n\n    /// @notice Returns the left \"sub-leaf\" of the State.\n    function leftLeaf(bytes32 root_, uint32 origin_) internal pure returns (bytes32) {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(root_, origin_));\n    }\n\n    /// @notice Returns the right \"sub-leaf\" of the State.\n    function rightLeaf(uint32 nonce_, uint40 blockNumber_, uint40 timestamp_, GasData gasData_)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(nonce_, blockNumber_, timestamp_, gasData_));\n    }\n\n    // ═══════════════════════════════════════════════ STATE SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns a historical Merkle root from the Origin contract.\n    function root(State state) internal pure returns (bytes32) {\n        return state.unwrap().index({index_: OFFSET_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns domain of chain where the Origin contract is deployed.\n    function origin(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns nonce of Origin contract at the time, when `root` was the Merkle root.\n    function nonce(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when `root` was saved in Origin.\n    function blockNumber(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when `root` was saved in Origin.\n    /// @dev This is the timestamp according to the origin chain.\n    function timestamp(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n\n    /// @notice Returns gas data for the chain.\n    function gasData(State state) internal pure returns (GasData) {\n        return GasDataLib.wrapGasData(state.unwrap().indexUint({index_: OFFSET_GAS_DATA, bytes_: GAS_DATA_LENGTH}));\n    }\n}\n\n// contracts/libs/memory/BaseMessage.sol\n\n/// BaseMessage is a memory view over the base message supported by Origin-Destination\ntype BaseMessage is uint256;\n\nusing BaseMessageLib for BaseMessage global;\n\n/// BaseMessage structure represents a base message sent via the Origin-Destination contracts.\n/// - It only contains data relevant to the base message, the rest of data is encoded in the message header.\n/// - `sender` and `recipient` for EVM chains are EVM addresses casted to bytes32, while preserving left-alignment.\n/// - `tips` and `request` parameters are specified by a message sender\n/// \u003e Origin will calculate minimum tips for given request and content length, and will reject messages with tips\n/// lower than that.\n///\n/// # Memory layout of BaseMessage fields\n///\n/// | Position   | Field     | Type    | Bytes | Description                            |\n/// | ---------- | --------- | ------- | ----- | -------------------------------------- |\n/// | [000..032) | tips      | uint256 | 32    | Encoded tips paid on origin chain      |\n/// | [032..064) | sender    | bytes32 | 32    | Sender address on origin chain         |\n/// | [064..096) | recipient | bytes32 | 32    | Recipient address on destination chain |\n/// | [096..116) | request   | uint160 | 20    | Encoded request for message execution  |\n/// | [104..AAA) | content   | bytes   | ??    | Content to be passed to recipient      |\nlibrary BaseMessageLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_TIPS = 0;\n    uint256 private constant OFFSET_SENDER = 32;\n    uint256 private constant OFFSET_RECIPIENT = 64;\n    uint256 private constant OFFSET_REQUEST = OFFSET_RECIPIENT + TIPS_LENGTH;\n    uint256 private constant OFFSET_CONTENT = OFFSET_REQUEST + REQUEST_LENGTH;\n\n    // ═══════════════════════════════════════════════ BASE MESSAGE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted BaseMessage payload with provided fields.\n     * @param tips_         Encoded tips information\n     * @param sender_       Sender address on origin chain\n     * @param recipient_    Recipient address on destination chain\n     * @param request_      Encoded request for message execution\n     * @param content_      Raw content to be passed to recipient on destination chain\n     * @return Formatted base message\n     */\n    function formatBaseMessage(Tips tips_, bytes32 sender_, bytes32 recipient_, Request request_, bytes memory content_)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return abi.encodePacked(tips_, sender_, recipient_, request_, content_);\n    }\n\n    /**\n     * @notice Returns a BaseMessage view over the given payload.\n     * @dev Will revert if the payload is not a base message.\n     */\n    function castToBaseMessage(bytes memory payload) internal pure returns (BaseMessage) {\n        return castToBaseMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a BaseMessage view.\n     * @dev Will revert if the memory view is not over a base message payload.\n     */\n    function castToBaseMessage(MemView memView) internal pure returns (BaseMessage) {\n        if (!isBaseMessage(memView)) revert UnformattedBaseMessage();\n        return BaseMessage.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted BaseMessage.\n    function isBaseMessage(MemView memView) internal pure returns (bool) {\n        // Check if sender, recipient, tips fields exist\n        return (memView.len() \u003e= OFFSET_CONTENT);\n        // Content could be empty, so we don't check that\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(BaseMessage baseMessage) internal pure returns (MemView) {\n        return MemView.wrap(BaseMessage.unwrap(baseMessage));\n    }\n\n    /// @notice Returns baseMessage's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        // We hash \"tips\" and \"everything but tips\" to make tips proofs easier to verify\n        return MerkleMath.getParent(baseMessage.tips().leaf(), baseMessage.bodyLeaf());\n    }\n\n    /// @notice Returns hash for the \"everything but tips\" part of the base message.\n    function bodyLeaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_SENDER}).keccak();\n    }\n\n    // ═══════════════════════════════════════════ BASE MESSAGE SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips paid on origin chain.\n    function tips(BaseMessage baseMessage) internal pure returns (Tips) {\n        return TipsLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_TIPS, bytes_: TIPS_LENGTH})));\n    }\n\n    /// @notice Returns sender address on origin chain.\n    function sender(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_SENDER, bytes_: 32});\n    }\n\n    /// @notice Returns recipient address on destination chain.\n    function recipient(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_RECIPIENT, bytes_: 32});\n    }\n\n    /// @notice Returns an encoded request for message execution on destination chain.\n    function request(BaseMessage baseMessage) internal pure returns (Request) {\n        return RequestLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_REQUEST, bytes_: REQUEST_LENGTH})));\n    }\n\n    /// @notice Returns an untyped memory view over the content to be passed to recipient.\n    function content(BaseMessage baseMessage) internal pure returns (MemView) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_CONTENT});\n    }\n}\n\n// contracts/base/MessagingBase.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for all messaging contracts.\n * - Provides context on the local chain's domain.\n * - Provides ownership functionality.\n * - Will be providing pausing functionality when it is implemented.\n */\nabstract contract MessagingBase is MultiCallable, Versioned, Ownable2StepUpgradeable {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @notice Domain of the local chain, set once upon contract creation\n    uint32 public immutable localDomain;\n    // @notice Domain of the Synapse chain, set once upon contract creation\n    uint32 public immutable synapseDomain;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev gap for upgrade safety\n    uint256[50] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    constructor(string memory version_, uint32 synapseDomain_) Versioned(version_) {\n        localDomain = ChainContext.chainId();\n        synapseDomain = synapseDomain_;\n    }\n\n    // TODO: Implement pausing\n\n    /**\n     * @dev Should be impossible to renounce ownership;\n     * we override OpenZeppelin OwnableUpgradeable's\n     * implementation of renounceOwnership to make it a no-op\n     */\n    function renounceOwnership() public override onlyOwner {} //solhint-disable-line no-empty-blocks\n}\n\n// contracts/libs/memory/Message.sol\n\n/// Message is a memory over over a formatted message payload.\ntype Message is uint256;\n\nusing MessageLib for Message global;\n\n/// Library for formatting the various messages supported by Origin and Destination.\n///\n/// # Message memory layout\n///\n/// | Position   | Field  | Type    | Bytes | Description                                             |\n/// | ---------- | ------ | ------- | ----- | ------------------------------------------------------- |\n/// | [000..017) | header | uint136 | 17    | Encoded general routing information for the message     |\n/// | [017..AAA) | body   | bytes   | ??    | Formatted payload (according to flag) with message body |\nlibrary MessageLib {\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MemViewLib for bytes;\n    using HeaderLib for MemView;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_HEADER = 0;\n    uint256 private constant OFFSET_BODY = OFFSET_HEADER + HEADER_LENGTH;\n\n    // ══════════════════════════════════════════════════ MESSAGE ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns formatted message with provided fields.\n     * @param header_   Encoded general routing information for the message\n     * @param body_     Formatted payload (according to flag) with message body\n     * @return Formatted message\n     */\n    function formatMessage(Header header_, bytes memory body_) internal pure returns (bytes memory) {\n        return abi.encodePacked(header_, body_);\n    }\n\n    /**\n     * @notice Returns a Message view over for the given payload.\n     * @dev Will revert if the payload is not a message payload.\n     */\n    function castToMessage(bytes memory payload) internal pure returns (Message) {\n        return castToMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Message view.\n     * @dev Will revert if the memory view is not over a message payload.\n     */\n    function castToMessage(MemView memView) internal pure returns (Message) {\n        if (!isMessage(memView)) revert UnformattedMessage();\n        return Message.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Message.\n     */\n    function isMessage(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Check if headers exist in the payload\n        if (length \u003c OFFSET_BODY) return false;\n        // Check that Header is valid\n        uint256 paddedHeader = _header(memView);\n        if (!HeaderLib.isHeader(paddedHeader)) return false;\n        // Check that body is formatted according to the flag\n        // Only Base/Manager message flags exist\n        if (HeaderLib.wrapPadded(paddedHeader).flag() == MessageFlag.Base) {\n            // Check if body is a formatted base message\n            return _body(memView).isBaseMessage();\n        } else {\n            // Check if body is a formatted calldata for AgentManager call\n            return _body(memView).isCallData();\n        }\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Message message) internal pure returns (MemView) {\n        return MemView.wrap(Message.unwrap(message));\n    }\n\n    /// @notice Returns message's hash: a leaf to be inserted in the Merkle tree.\n    function leaf(Message message) internal pure returns (bytes32) {\n        // We hash header and body separately to make message proofs easier to verify\n        Header header_ = message.header();\n        // Only Base/Manager message flags exist\n        if (header_.flag() == MessageFlag.Base) {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToBaseMessage().leaf());\n        } else {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToCallData().leaf());\n        }\n    }\n\n    // ══════════════════════════════════════════════ MESSAGE SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns message's encoded header field.\n    function header(Message message) internal pure returns (Header) {\n        return HeaderLib.wrapPadded((message.unwrap().indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH})));\n    }\n\n    /// @notice Returns message's body field as an untyped memory view.\n    function body(Message message) internal pure returns (MemView) {\n        MemView memView = message.unwrap();\n        return _body(memView);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns message's padded header without checking that it is a valid header.\n    function _header(MemView memView) private pure returns (uint256) {\n        return memView.indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH});\n    }\n\n    /// @dev Returns an untyped memory view over the body field without checking\n    /// if the whole payload or the body are properly formatted.\n    function _body(MemView memView) private pure returns (MemView) {\n        return memView.sliceFrom({index_: OFFSET_BODY});\n    }\n}\n\n// contracts/base/AgentSecured.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for messaging contracts that are secured by the agent manager.\n * `AgentSecured` relies on `AgentManager` to provide the following functionality:\n * - Keep track of agents and their statuses.\n * - Pass agent-signed statements that were verified by the agent manager.\n * - These statements are considered valid indefinitely, unless the agent is disputed.\n * - Disputes are opened and resolved by the agent manager.\n * \u003e `AgentSecured` implementation should never use statements signed by agents that are disputed.\n */\nabstract contract AgentSecured is MessagingBase, IAgentSecured {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    address public immutable agentManager;\n\n    /// @inheritdoc IAgentSecured\n    address public immutable inbox;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    // (agent index =\u003e their dispute status: flag, openedAt, resolvedAt)\n    mapping(uint32 =\u003e DisputeStatus) internal _disputes;\n\n    /// @dev gap for upgrade safety\n    uint256[49] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    modifier onlyAgentManager() {\n        if (msg.sender != agentManager) revert CallerNotAgentManager();\n        _;\n    }\n\n    modifier onlyInbox() {\n        if (msg.sender != inbox) revert CallerNotInbox();\n        _;\n    }\n\n    constructor(string memory version_, uint32 synapseDomain_, address agentManager_, address inbox_)\n        MessagingBase(version_, synapseDomain_)\n    {\n        agentManager = agentManager_;\n        inbox = inbox_;\n    }\n\n    // ════════════════════════════════════════════ ONLY AGENT MANAGER ═════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external onlyAgentManager {\n        uint40 openedAt = ChainContext.blockTimestamp();\n        DisputeStatus memory status = DisputeStatus({flag: DisputeFlag.Pending, openedAt: openedAt, resolvedAt: 0});\n        _disputes[guardIndex] = status;\n        _disputes[notaryIndex] = status;\n    }\n\n    /// @inheritdoc IAgentSecured\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external onlyAgentManager {\n        // Update the dispute status of the slashed agent first.\n        uint40 resolvedAt = ChainContext.blockTimestamp();\n        _disputes[slashedIndex].flag = DisputeFlag.Slashed;\n        _disputes[slashedIndex].resolvedAt = resolvedAt;\n        // Mark the rival agent as not disputed, if there was an ongoing dispute.\n        if (rivalIndex != 0) {\n            _disputes[rivalIndex].flag = DisputeFlag.None;\n            _disputes[rivalIndex].resolvedAt = resolvedAt;\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function agentStatus(address agent) external view returns (AgentStatus memory) {\n        return _agentStatus(agent);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status) {\n        return _getAgent(index);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory) {\n        return _disputes[agentIndex];\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns status of the given agent: (flag, domain, index).\n    function _agentStatus(address agent) internal view returns (AgentStatus memory) {\n        return IAgentManager(agentManager).agentStatus(agent);\n    }\n\n    /// @dev Returns agent and their status for a given agent index. Returns zero values for non existing indexes.\n    function _getAgent(uint256 index) internal view returns (address agent, AgentStatus memory status) {\n        return IAgentManager(agentManager).getAgent(index);\n    }\n\n    /// @dev Checks if a Dispute exists for the given Notary. This function returns true, if\n    /// Notary is in ongoing Dispute, or if Dispute was resolved not in Notary's favor.\n    /// In both cases we can't trust Notary's data.\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeExists(uint32 notaryIndex) internal view returns (bool) {\n        return _disputes[notaryIndex].flag != DisputeFlag.None;\n    }\n\n    /// @dev Checks if a Notary recently won a Dispute and is still in the \"post-dispute\" timeout period.\n    /// In this period we still can't trust Notary's data, though we can optimistically assume that\n    /// that the data will be correct after the timeout (assuming no new Disputes are opened).\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeTimeout(uint32 notaryIndex) internal view returns (bool) {\n        DisputeStatus memory status = _disputes[notaryIndex];\n        // Exit early if Notary is in ongoing Dispute / slashed.\n        if (status.flag != DisputeFlag.None) return false;\n        // Check if Notary has been in any Dispute at all.\n        if (status.openedAt == 0) return false;\n        // Otherwise check if the Dispute timeout is still active.\n        return block.timestamp \u003c status.resolvedAt + DISPUTE_TIMEOUT_NOTARY;\n    }\n}\n\n// contracts/hubs/StateHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StateHub` is a parent contract for `Origin`. It is responsible for the following:\n/// - Keeping track of the historical Origin Merkle Tree containing all the message hashes.\n/// - Keeping track of the historical Origin States, as well as verifying their validity.\nabstract contract StateHub is AgentSecured, StateHubEvents, IStateHub {\n    using SafeCast for uint256;\n    using StateLib for bytes;\n\n    struct OriginState {\n        uint40 blockNumber;\n        uint40 timestamp;\n        GasData gasData;\n    }\n    // Bits left for tight packing: 80\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Historical Merkle Tree\n    /// Note: Takes two storage slots\n    HistoricalTree private _tree;\n\n    /// @dev All historical contract States\n    OriginState[] private _originStates;\n\n    /// @dev gap for upgrade safety\n    uint256[47] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IStateHub\n    function isValidState(bytes memory statePayload) external view returns (bool isValid) {\n        // This will revert if payload is not a formatted state\n        State state = statePayload.castToState();\n        return _isValidState(state);\n    }\n\n    /// @inheritdoc IStateHub\n    function statesAmount() external view returns (uint256) {\n        return _originStates.length;\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestLatestState() external view returns (bytes memory stateData) {\n        // This never underflows, assuming the contract was initialized\n        return suggestState(_nextNonce() - 1);\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestState(uint32 nonce) public view returns (bytes memory stateData) {\n        // This will revert if nonce is out of range\n        bytes32 root = _tree.root(nonce);\n        return _formatOriginState(_originStates[nonce], root, localDomain, nonce);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Initializes the saved states list by inserting a state for an empty Merkle Tree.\n    function _initializeStates() internal {\n        // This should only be called once, when the contract is initialized\n        // This will revert if _tree.roots is non-empty\n        bytes32 savedRoot = _tree.initializeRoots();\n        // Save root for empty merkle _tree with block number and timestamp of initialization\n        _saveState(savedRoot, _toOriginState());\n    }\n\n    /// @dev Inserts leaf into the Merkle Tree and saves the updated origin State.\n    function _insertAndSave(bytes32 leaf) internal {\n        bytes32 newRoot = _tree.insert(leaf);\n        _saveState(newRoot, _toOriginState());\n    }\n\n    /// @dev Saves an updated state of the Origin contract\n    function _saveState(bytes32 root, OriginState memory state) internal {\n        uint32 nonce = _nextNonce();\n        _originStates.push(state);\n        // Emit event with raw state data\n        emit StateSaved(_formatOriginState(state, root, localDomain, nonce));\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns nonce of the next sent message: the amount of saved States so far.\n    /// This always equals to \"total amount of sent messages\" plus 1.\n    function _nextNonce() internal view returns (uint32) {\n        // TODO: consider using more than 32 bits for origin nonces\n        return _originStates.length.toUint32();\n    }\n\n    /// @dev Checks if a state is valid, i.e. if it matches the historical one.\n    /// Reverts, if state refers to another Origin contract.\n    function _isValidState(State state) internal view returns (bool) {\n        // Check if state refers to this contract\n        if (state.origin() != localDomain) revert IncorrectOriginDomain();\n        // Check if nonce exists\n        uint32 nonce = state.nonce();\n        if (nonce \u003e= _originStates.length) return false;\n        // Check if state root matches the historical one\n        if (state.root() != _tree.root(nonce)) return false;\n        // Check if state metadata matches the historical one\n        return _areEqual(state, _originStates[nonce]);\n    }\n\n    // ═════════════════════════════════════════════ STRUCT FORMATTING ═════════════════════════════════════════════════\n\n    /// @dev Returns a formatted payload for a stored OriginState.\n    function _formatOriginState(OriginState memory originState, bytes32 root, uint32 origin, uint32 nonce)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return StateLib.formatState({\n            root_: root,\n            origin_: origin,\n            nonce_: nonce,\n            blockNumber_: originState.blockNumber,\n            timestamp_: originState.timestamp,\n            gasData_: originState.gasData\n        });\n    }\n\n    /// @dev Child contract should implement the logic for getting the current gas data from the gas oracle\n    /// to be saved as part of the Origin State.\n    // solhint-disable-next-line ordering\n    function _fetchGasData() internal view virtual returns (GasData);\n\n    /// @dev Returns a OriginState struct to save in the contract.\n    function _toOriginState() internal view returns (OriginState memory originState) {\n        originState.blockNumber = ChainContext.blockNumber();\n        originState.timestamp = ChainContext.blockTimestamp();\n        originState.gasData = _fetchGasData();\n    }\n\n    /// @dev Checks that a state and its Origin representation are equal.\n    function _areEqual(State state, OriginState memory originState) internal pure returns (bool) {\n        return state.blockNumber() == originState.blockNumber \u0026\u0026 state.timestamp() == originState.timestamp;\n    }\n}\n\n// contracts/Origin.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Origin` contract is used for sending messages to remote chains. It is done\n/// by inserting the message hashes into the Origin Merkle, which makes it possible to\n/// prove that message was sent using the Merkle proof against the Origin Merkle Root. This essentially\n/// compresses the list of messages into a single 32-byte value that needs to be stored on the destination chain.\n/// `Origin` is responsible for the following:\n/// - Formatting the sent message payloads, and inserting their hashes into the Origin Merkle Tree.\n/// - Keeping track of its own historical states (see parent contract `StateHub`).\n/// - Enforcing minimum tip values for sent base messages based on the provided execution requests.\n/// - Distributing the collected tips upon request from a local `AgentManager` contract.\ncontract Origin is StateHub, OriginEvents, InterfaceOrigin {\n    using MemViewLib for bytes;\n    using MessageLib for bytes;\n    using TipsLib for bytes;\n    using TypeCasts for address;\n\n    address public immutable gasOracle;\n\n    modifier onlyRemoteDestination(uint32 destination) {\n        if (destination == localDomain) revert IncorrectDestinationDomain();\n        _;\n    }\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_, address gasOracle_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {\n        gasOracle = gasOracle_;\n    }\n\n    /// @notice Initializes Origin contract:\n    /// - msg.sender is set as contract owner\n    /// - State of \"empty merkle tree\" is saved\n    function initialize() external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize \"states\": state of an \"empty merkle tree\" is saved\n        _initializeStates();\n    }\n\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable onlyRemoteDestination(destination) returns (uint32 messageNonce, bytes32 messageHash) {\n        // Check that content is not too large\n        if (content.length \u003e MAX_CONTENT_BYTES) revert ContentLengthTooBig();\n        // This will revert if msg.value is lower than value of minimum tips\n        Tips tips = _getMinimumTips(destination, paddedRequest, content.length).matchValue(msg.value);\n        Request request = RequestLib.wrapPadded(paddedRequest);\n        // Format the BaseMessage body\n        bytes memory body = BaseMessageLib.formatBaseMessage({\n            sender_: msg.sender.addressToBytes32(),\n            recipient_: recipient,\n            tips_: tips,\n            request_: request,\n            content_: content\n        });\n        // Send the message\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Base, body);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        onlyAgentManager\n        onlyRemoteDestination(destination)\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // AgentManager (checked via modifier) is responsible for constructing the calldata payload correctly.\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Manager, payload);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function withdrawTips(address recipient, uint256 amount) external onlyAgentManager {\n        if (address(this).balance \u003c amount) revert InsufficientEthBalance();\n        (bool success,) = recipient.call{value: amount}(\"\");\n        if (!success) revert EthTransferFailed();\n        emit TipWithdrawalCompleted(recipient, amount);\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue)\n    {\n        return _getMinimumTips(destination, paddedRequest, contentLength).value();\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Sends the given message to the specified destination. Message hash is inserted\n    /// into the Origin Merkle Tree, which will enable message execution on destination chain.\n    function _sendMessage(uint32 destination, uint32 optimisticPeriod, MessageFlag flag, bytes memory body)\n        internal\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // Format the message header\n        messageNonce = _nextNonce();\n        Header header = flag.encodeHeader({\n            origin_: localDomain,\n            nonce_: messageNonce,\n            destination_: destination,\n            optimisticPeriod_: optimisticPeriod\n        });\n        // Format the full message payload\n        bytes memory msgPayload = MessageLib.formatMessage(header, body);\n        // Insert new leaf into the Origin Merkle Tree and save the updated state\n        messageHash = msgPayload.castToMessage().leaf();\n        _insertAndSave(messageHash);\n        // Emit event with message information\n        emit Sent(messageHash, messageNonce, destination, msgPayload);\n        // Update the gas oracle data. We do this after the provided tips are checked so that\n        // the provided message is sent in the event that the gas oracle data is updated to a higher value.\n        InterfaceGasOracle(gasOracle).updateGasData(destination);\n        // TODO: consider doing this before the message is sent, while adjusting GasOracle.getMinimumTips() to\n        // use the pending gas oracle data.\n    }\n\n    /// @dev Returns the minimum tips for sending a message to the given destination with the given request and content.\n    function _getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        internal\n        view\n        returns (Tips)\n    {\n        return\n            TipsLib.wrapPadded(InterfaceGasOracle(gasOracle).getMinimumTips(destination, paddedRequest, contentLength));\n    }\n\n    /// @dev Gets the current gas data from the gas oracle to be saved as part of the Origin State.\n    function _fetchGasData() internal view override returns (GasData) {\n        return GasDataLib.wrapGasData(InterfaceGasOracle(gasOracle).getGasData());\n    }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[],"name":"CallerNotAgentManager","type":"error"},{"inputs":[],"name":"IncorrectOriginDomain","type":"error"},{"inputs":[],"name":"IncorrectVersionLength","type":"error"},{"inputs":[],"name":"IndexedTooMuch","type":"error"},{"inputs":[],"name":"NotEnoughLeafs","type":"error"},{"inputs":[],"name":"UnallocatedMemory","type":"error"},{"inputs":[],"name":"UnformattedState","type":"error"},{"inputs":[],"name":"ViewOverrun","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"state","type":"bytes"}],"name":"StateSaved","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"agentManager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"agent","type":"address"}],"name":"agentStatus","outputs":[{"components":[{"internalType":"enum AgentFlag","name":"flag","type":"uint8"},{"internalType":"uint32","name":"domain","type":"uint32"},{"internalType":"uint32","name":"index","type":"uint32"}],"internalType":"struct AgentStatus","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getAgent","outputs":[{"internalType":"address","name":"agent","type":"address"},{"components":[{"internalType":"enum AgentFlag","name":"flag","type":"uint8"},{"internalType":"uint32","name":"domain","type":"uint32"},{"internalType":"uint32","name":"index","type":"uint32"}],"internalType":"struct AgentStatus","name":"status","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"inbox","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"statePayload","type":"bytes"}],"name":"isValidState","outputs":[{"internalType":"bool","name":"isValid","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"agentIndex","type":"uint32"}],"name":"latestDisputeStatus","outputs":[{"components":[{"internalType":"enum DisputeFlag","name":"flag","type":"uint8"},{"internalType":"uint40","name":"openedAt","type":"uint40"},{"internalType":"uint40","name":"resolvedAt","type":"uint40"}],"internalType":"struct DisputeStatus","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"localDomain","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bool","name":"allowFailure","type":"bool"},{"internalType":"bytes","name":"callData","type":"bytes"}],"internalType":"struct MultiCallable.Call[]","name":"calls","type":"tuple[]"}],"name":"multicall","outputs":[{"components":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"bytes","name":"returnData","type":"bytes"}],"internalType":"struct MultiCallable.Result[]","name":"callResults","type":"tuple[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"guardIndex","type":"uint32"},{"internalType":"uint32","name":"notaryIndex","type":"uint32"}],"name":"openDispute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"slashedIndex","type":"uint32"},{"internalType":"uint32","name":"rivalIndex","type":"uint32"}],"name":"resolveDispute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"statesAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"suggestLatestState","outputs":[{"internalType":"bytes","name":"stateData","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"nonce","type":"uint32"}],"name":"suggestState","outputs":[{"internalType":"bytes","name":"stateData","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"synapseDomain","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"versionString","type":"string"}],"stateMutability":"view","type":"function"}],"userDoc":{"events":{"StateSaved(bytes)":{"notice":"Emitted when a new Origin State is saved after a message was sent."}},"kind":"user","methods":{"agentManager()":{"notice":"Returns the address of the local AgentManager contract, which is treated as the \"source of truth\" for agent statuses."},"agentStatus(address)":{"notice":"Returns (flag, domain, index) for a given agent. See Structures.sol for details."},"getAgent(uint256)":{"notice":"Returns agent address and their current status for a given agent index."},"inbox()":{"notice":"Returns the address of the local Inbox contract, which is treated as the \"source of truth\" for agent-signed statements."},"isValidState(bytes)":{"notice":"Check that a given state is valid: matches the historical state of Origin contract. Note: any Agent including an invalid state in their snapshot will be slashed upon providing the snapshot and agent signature for it to Origin contract."},"latestDisputeStatus(uint32)":{"notice":"Returns (flag, openedAt, resolvedAt) that describes the latest status of the latest dispute for an agent with a given index."},"localDomain()":{"notice":"Domain of the local chain, set once upon contract creation"},"multicall((bool,bytes)[])":{"notice":"Aggregates a few calls to this contract into one multicall without modifying `msg.sender`."},"openDispute(uint32,uint32)":{"notice":"Local AgentManager should call this function to indicate that a dispute between a Guard and a Notary has been opened."},"resolveDispute(uint32,uint32)":{"notice":"Local AgentManager should call this function to indicate that a dispute has been resolved due to one of the agents being slashed. \u003e `rivalIndex` will be ZERO, if the slashed agent was not in the Dispute."},"statesAmount()":{"notice":"Returns the amount of saved states so far."},"suggestLatestState()":{"notice":"Suggest the data (state after latest sent message) to sign for an Agent. Note: signing the suggested state data will will never lead to slashing of the actor, assuming they have confirmed that the block, which number is included in the data, is not subject to reorganization (which is different for every observed chain)."},"suggestState(uint32)":{"notice":"Given the historical nonce, suggest the state data to sign for an Agent. Note: signing the suggested state data will will never lead to slashing of the actor, assuming they have confirmed that the block, which number is included in the data, is not subject to reorganization (which is different for every observed chain)."}},"notice":"`StateHub` is a parent contract for `Origin`. It is responsible for the following: - Keeping track of the historical Origin Merkle Tree containing all the message hashes. - Keeping track of the historical Origin States, as well as verifying their validity.","version":1},"developerDoc":{"kind":"dev","methods":{"acceptOwnership()":{"details":"The new owner accepts the ownership transfer."},"agentStatus(address)":{"details":"Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud, but their status is not updated to Slashed yet.","params":{"agent":"Agent address"},"returns":{"_0":"Status for the given agent: (flag, domain, index)."}},"getAgent(uint256)":{"details":"Will return empty values if agent with given index doesn't exist.","params":{"index":"Agent index in the Agent Merkle Tree"},"returns":{"agent":"   Agent address","status":"  Status for the given agent: (flag, domain, index)"}},"isValidState(bytes)":{"details":"Will revert if any of these is true:  - State payload is not properly formatted.","params":{"statePayload":"Raw payload with state data"},"returns":{"isValid":"         Whether the provided state is valid"}},"latestDisputeStatus(uint32)":{"details":"Will return empty values if agent with given index doesn't exist.","params":{"agentIndex":"Agent index in the Agent Merkle Tree"},"returns":{"_0":"Latest dispute status for the given agent: (flag, openedAt, resolvedAt)"}},"openDispute(uint32,uint32)":{"params":{"guardIndex":"Index of the Guard in the Agent Merkle Tree","notaryIndex":"Index of the Notary in the Agent Merkle Tree"}},"owner()":{"details":"Returns the address of the current owner."},"pendingOwner()":{"details":"Returns the address of the pending owner."},"renounceOwnership()":{"details":"Should be impossible to renounce ownership; we override OpenZeppelin OwnableUpgradeable's implementation of renounceOwnership to make it a no-op"},"resolveDispute(uint32,uint32)":{"params":{"rivalIndex":"Index of the their Dispute Rival in the Agent Merkle Tree","slashedIndex":"Index of the slashed agent in the Agent Merkle Tree"}},"statesAmount()":{"details":"This includes the initial state of \"empty Origin Merkle Tree\"."},"suggestLatestState()":{"returns":{"stateData":"    Raw payload with the latest state data"}},"suggestState(uint32)":{"params":{"nonce":"Historical nonce to form a state"},"returns":{"stateData":"    Raw payload with historical state data"}},"transferOwnership(address)":{"details":"Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. Can only be called by the current owner."}},"stateVariables":{"__GAP":{"details":"gap for upgrade safety"},"_originStates":{"details":"All historical contract States"},"_tree":{"details":"Historical Merkle Tree Note: Takes two storage slots"}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"CallerNotAgentManager\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectOriginDomain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectVersionLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexedTooMuch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotEnoughLeafs\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnallocatedMemory\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnformattedState\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ViewOverrun\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferStarted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"state\",\"type\":\"bytes\"}],\"name\":\"StateSaved\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"agentManager\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"agent\",\"type\":\"address\"}],\"name\":\"agentStatus\",\"outputs\":[{\"components\":[{\"internalType\":\"enum AgentFlag\",\"name\":\"flag\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"domain\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"index\",\"type\":\"uint32\"}],\"internalType\":\"struct AgentStatus\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getAgent\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"agent\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"enum AgentFlag\",\"name\":\"flag\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"domain\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"index\",\"type\":\"uint32\"}],\"internalType\":\"struct AgentStatus\",\"name\":\"status\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"inbox\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"statePayload\",\"type\":\"bytes\"}],\"name\":\"isValidState\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isValid\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"agentIndex\",\"type\":\"uint32\"}],\"name\":\"latestDisputeStatus\",\"outputs\":[{\"components\":[{\"internalType\":\"enum DisputeFlag\",\"name\":\"flag\",\"type\":\"uint8\"},{\"internalType\":\"uint40\",\"name\":\"openedAt\",\"type\":\"uint40\"},{\"internalType\":\"uint40\",\"name\":\"resolvedAt\",\"type\":\"uint40\"}],\"internalType\":\"struct DisputeStatus\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"localDomain\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"allowFailure\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"struct MultiCallable.Call[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"multicall\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"struct MultiCallable.Result[]\",\"name\":\"callResults\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"guardIndex\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"notaryIndex\",\"type\":\"uint32\"}],\"name\":\"openDispute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"slashedIndex\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"rivalIndex\",\"type\":\"uint32\"}],\"name\":\"resolveDispute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"statesAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"suggestLatestState\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"stateData\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"nonce\",\"type\":\"uint32\"}],\"name\":\"suggestState\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"stateData\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"synapseDomain\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"versionString\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"acceptOwnership()\":{\"details\":\"The new owner accepts the ownership transfer.\"},\"agentStatus(address)\":{\"details\":\"Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud, but their status is not updated to Slashed yet.\",\"params\":{\"agent\":\"Agent address\"},\"returns\":{\"_0\":\"Status for the given agent: (flag, domain, index).\"}},\"getAgent(uint256)\":{\"details\":\"Will return empty values if agent with given index doesn't exist.\",\"params\":{\"index\":\"Agent index in the Agent Merkle Tree\"},\"returns\":{\"agent\":\"   Agent address\",\"status\":\"  Status for the given agent: (flag, domain, index)\"}},\"isValidState(bytes)\":{\"details\":\"Will revert if any of these is true:  - State payload is not properly formatted.\",\"params\":{\"statePayload\":\"Raw payload with state data\"},\"returns\":{\"isValid\":\"         Whether the provided state is valid\"}},\"latestDisputeStatus(uint32)\":{\"details\":\"Will return empty values if agent with given index doesn't exist.\",\"params\":{\"agentIndex\":\"Agent index in the Agent Merkle Tree\"},\"returns\":{\"_0\":\"Latest dispute status for the given agent: (flag, openedAt, resolvedAt)\"}},\"openDispute(uint32,uint32)\":{\"params\":{\"guardIndex\":\"Index of the Guard in the Agent Merkle Tree\",\"notaryIndex\":\"Index of the Notary in the Agent Merkle Tree\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pendingOwner()\":{\"details\":\"Returns the address of the pending owner.\"},\"renounceOwnership()\":{\"details\":\"Should be impossible to renounce ownership; we override OpenZeppelin OwnableUpgradeable's implementation of renounceOwnership to make it a no-op\"},\"resolveDispute(uint32,uint32)\":{\"params\":{\"rivalIndex\":\"Index of the their Dispute Rival in the Agent Merkle Tree\",\"slashedIndex\":\"Index of the slashed agent in the Agent Merkle Tree\"}},\"statesAmount()\":{\"details\":\"This includes the initial state of \\\"empty Origin Merkle Tree\\\".\"},\"suggestLatestState()\":{\"returns\":{\"stateData\":\"    Raw payload with the latest state data\"}},\"suggestState(uint32)\":{\"params\":{\"nonce\":\"Historical nonce to form a state\"},\"returns\":{\"stateData\":\"    Raw payload with historical state data\"}},\"transferOwnership(address)\":{\"details\":\"Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. Can only be called by the current owner.\"}},\"stateVariables\":{\"__GAP\":{\"details\":\"gap for upgrade safety\"},\"_originStates\":{\"details\":\"All historical contract States\"},\"_tree\":{\"details\":\"Historical Merkle Tree Note: Takes two storage slots\"}},\"version\":1},\"userdoc\":{\"events\":{\"StateSaved(bytes)\":{\"notice\":\"Emitted when a new Origin State is saved after a message was sent.\"}},\"kind\":\"user\",\"methods\":{\"agentManager()\":{\"notice\":\"Returns the address of the local AgentManager contract, which is treated as the \\\"source of truth\\\" for agent statuses.\"},\"agentStatus(address)\":{\"notice\":\"Returns (flag, domain, index) for a given agent. See Structures.sol for details.\"},\"getAgent(uint256)\":{\"notice\":\"Returns agent address and their current status for a given agent index.\"},\"inbox()\":{\"notice\":\"Returns the address of the local Inbox contract, which is treated as the \\\"source of truth\\\" for agent-signed statements.\"},\"isValidState(bytes)\":{\"notice\":\"Check that a given state is valid: matches the historical state of Origin contract. Note: any Agent including an invalid state in their snapshot will be slashed upon providing the snapshot and agent signature for it to Origin contract.\"},\"latestDisputeStatus(uint32)\":{\"notice\":\"Returns (flag, openedAt, resolvedAt) that describes the latest status of the latest dispute for an agent with a given index.\"},\"localDomain()\":{\"notice\":\"Domain of the local chain, set once upon contract creation\"},\"multicall((bool,bytes)[])\":{\"notice\":\"Aggregates a few calls to this contract into one multicall without modifying `msg.sender`.\"},\"openDispute(uint32,uint32)\":{\"notice\":\"Local AgentManager should call this function to indicate that a dispute between a Guard and a Notary has been opened.\"},\"resolveDispute(uint32,uint32)\":{\"notice\":\"Local AgentManager should call this function to indicate that a dispute has been resolved due to one of the agents being slashed. \u003e `rivalIndex` will be ZERO, if the slashed agent was not in the Dispute.\"},\"statesAmount()\":{\"notice\":\"Returns the amount of saved states so far.\"},\"suggestLatestState()\":{\"notice\":\"Suggest the data (state after latest sent message) to sign for an Agent. Note: signing the suggested state data will will never lead to slashing of the actor, assuming they have confirmed that the block, which number is included in the data, is not subject to reorganization (which is different for every observed chain).\"},\"suggestState(uint32)\":{\"notice\":\"Given the historical nonce, suggest the state data to sign for an Agent. Note: signing the suggested state data will will never lead to slashing of the actor, assuming they have confirmed that the block, which number is included in the data, is not subject to reorganization (which is different for every observed chain).\"}},\"notice\":\"`StateHub` is a parent contract for `Origin`. It is responsible for the following: - Keeping track of the historical Origin Merkle Tree containing all the message hashes. - Keeping track of the historical Origin States, as well as verifying their validity.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Origin.sol\":\"StateHub\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Origin.sol\":{\"keccak256\":\"0x96775924f147f3d1f8df8cdf56731fe52a15af8d8e12e608efb8158c112b18cd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e642a27f5fab3c62b4c02e9754e9e42b1cf2e5381dbea9d3d106d23b7772ebe6\",\"dweb:/ipfs/QmUwn7ZyBvPkjnMuK8ZMSexBUdNQnVtxwyoAyT4DXLQjra\"]}},\"version\":1}"},"hashes":{"acceptOwnership()":"79ba5097","agentManager()":"7622f78d","agentStatus(address)":"28f3fac9","getAgent(uint256)":"2de5aaf7","inbox()":"fb0e722b","isValidState(bytes)":"a9dcf22d","latestDisputeStatus(uint32)":"dfadd81a","localDomain()":"8d3638f4","multicall((bool,bytes)[])":"60fc8466","openDispute(uint32,uint32)":"a2155c34","owner()":"8da5cb5b","pendingOwner()":"e30c3978","renounceOwnership()":"715018a6","resolveDispute(uint32,uint32)":"61169218","statesAmount()":"f2437942","suggestLatestState()":"c0b56f7c","suggestState(uint32)":"b4596b4b","synapseDomain()":"717b8638","transferOwnership(address)":"f2fde38b","version()":"54fd4d50"}},"solidity/Origin.sol:StateHubEvents":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/OriginEvents.sol\n\n/// @notice A collection of events emitted by the Origin contract\nabstract contract OriginEvents {\n    /**\n     * @notice Emitted when a new message is sent.\n     * @param messageHash   Hash of message; the leaf inserted to the Merkle tree for the message\n     * @param nonce         Nonce of sent message (starts from 1)\n     * @param destination   Destination domain\n     * @param message       Raw bytes of message\n     */\n    event Sent(bytes32 indexed messageHash, uint32 indexed nonce, uint32 indexed destination, bytes message);\n\n    /**\n     * @notice Emitted when a tip withdrawal is completed.\n     * @param actor     Actor address\n     * @param tip       Tip value, denominated in local domain's wei\n     */\n    event TipWithdrawalCompleted(address actor, uint256 tip);\n}\n\n// contracts/events/StateHubEvents.sol\n\n/// @notice A collection of events emitted by the StateHub contract\nabstract contract StateHubEvents {\n    /**\n     * @notice Emitted when a new Origin State is saved after a message was sent.\n     * @param state     Raw payload with state data\n     */\n    event StateSaved(bytes state);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n    /**\n     * @notice Check that a given state is valid: matches the historical state of Origin contract.\n     * Note: any Agent including an invalid state in their snapshot will be slashed\n     * upon providing the snapshot and agent signature for it to Origin contract.\n     * @dev Will revert if any of these is true:\n     *  - State payload is not properly formatted.\n     * @param statePayload      Raw payload with state data\n     * @return isValid          Whether the provided state is valid\n     */\n    function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns the amount of saved states so far.\n     * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n     */\n    function statesAmount() external view returns (uint256);\n\n    /**\n     * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @return statePayload     Raw payload with the latest state data\n     */\n    function suggestLatestState() external view returns (bytes memory statePayload);\n\n    /**\n     * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @param nonce             Historical nonce to form a state\n     * @return statePayload     Raw payload with historical state data\n     */\n    function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/InterfaceGasOracle.sol\n\ninterface InterfaceGasOracle {\n    /**\n     * @notice Fetches the latest gas data for the chain from `Destination` contract,\n     * and uses it to update the oracle values for the requested chain.\n     * @param domain    Domain to update the gas data for\n     */\n    function updateGasData(uint32 domain) external;\n\n    /**\n     * @notice Returns the gas data for the local chain.\n     */\n    function getGasData() external view returns (uint256 paddedGasData);\n\n    /**\n     * @notice Returns the gas data for the given domain, in the decoded format.\n     * @param domain        Domain of chain to get gas data for\n     * @return gasPrice     Gas price for the chain (in Wei per gas unit)\n     * @return dataPrice    Calldata price (in Wei per byte of content)\n     * @return execBuffer   Tx fee safety buffer for message execution (in Wei)\n     * @return amortAttCost Amortized cost for attestation submission (in Wei)\n     * @return etherPrice   Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n     * @return markup       Markup for the message execution (in BWAD)\n     */\n    function getDecodedGasData(uint32 domain)\n        external\n        view\n        returns (\n            uint256 gasPrice,\n            uint256 dataPrice,\n            uint256 execBuffer,\n            uint256 amortAttCost,\n            uint256 etherPrice,\n            uint256 markup\n        );\n\n    /**\n     * @notice Returns the minimum tips for sending a message to a given destination.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return paddedTips       Padded encoded minimum tips information\n     */\n    function getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 paddedTips);\n}\n\n// contracts/interfaces/InterfaceOrigin.sol\n\ninterface InterfaceOrigin {\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /**\n     * @notice Send a message to the recipient located on destination domain.\n     * @dev Recipient has to conform to IMessageRecipient interface, otherwise message won't be delivered.\n     * Will revert if any of these is true:\n     * - `destination` is equal to contract's local domain\n     * - `content` length is greater than `MAX_CONTENT_BYTES`\n     * - `msg.value` is lower than value of minimum tips for the given message\n     * @param destination           Domain of destination chain\n     * @param recipient             Address of recipient on destination chain as bytes32\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param paddedRequest         Padded encoded message execution request on destination chain\n     * @param content               Raw bytes content of message\n     * @return messageNonce         Nonce of the sent message\n     * @return messageHash          Hash of the sent message\n     */\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable returns (uint32 messageNonce, bytes32 messageHash);\n\n    /**\n     * @notice Send a manager message to the destination domain.\n     * @dev This could only be called by AgentManager, which takes care of encoding the calldata payload.\n     * Note: (msgOrigin, proofMaturity) security args will be added to payload on the destination chain\n     * so that the AgentManager could verify where the Manager Message came from and how mature is the proof.\n     * Note: function is not payable, as no tips are required for sending a manager message.\n     * Will revert if `destination` is equal to contract's local domain.\n     * @param destination           Domain of destination chain\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param payload               Payload for calling AgentManager on destination chain (with extra security args)\n     */\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        returns (uint32 messageNonce, bytes32 messageHash);\n\n    // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Withdraws locked base message tips to the recipient.\n     * @dev Could only be called by a local AgentManager.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function withdrawTips(address recipient, uint256 amount) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the minimum tips value for sending a message to a given destination.\n     * @dev Using at least `tipsValue` as `msg.value` for `sendBaseMessage()`\n     * will guarantee that the message will be accepted.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return tipsValue        Minimum tips value for a message to be accepted\n     */\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue);\n}\n\n// contracts/libs/Constants.sol\n\n// Here we define common constants to enable their easier reusing later.\n\n// ══════════════════════════════════ MERKLE ═══════════════════════════════════\n/// @dev Height of the Agent Merkle Tree\nuint256 constant AGENT_TREE_HEIGHT = 32;\n/// @dev Height of the Origin Merkle Tree\nuint256 constant ORIGIN_TREE_HEIGHT = 32;\n/// @dev Height of the Snapshot Merkle Tree. Allows up to 64 leafs, e.g. up to 32 states\nuint256 constant SNAPSHOT_TREE_HEIGHT = 6;\n// ══════════════════════════════════ STRUCTS ══════════════════════════════════\n/// @dev See Attestation.sol: (bytes32,bytes32,uint32,uint40,uint40): 32+32+4+5+5\nuint256 constant ATTESTATION_LENGTH = 78;\n/// @dev See GasData.sol: (uint16,uint16,uint16,uint16,uint16,uint16): 2+2+2+2+2+2\nuint256 constant GAS_DATA_LENGTH = 12;\n/// @dev See Receipt.sol: (uint32,uint32,bytes32,bytes32,uint8,address,address,address): 4+4+32+32+1+20+20+20\nuint256 constant RECEIPT_LENGTH = 133;\n/// @dev See State.sol: (bytes32,uint32,uint32,uint40,uint40,GasData): 32+4+4+5+5+len(GasData)\nuint256 constant STATE_LENGTH = 50 + GAS_DATA_LENGTH;\n/// @dev Maximum amount of states in a single snapshot. Each state produces two leafs in the tree\nuint256 constant SNAPSHOT_MAX_STATES = 1 \u003c\u003c (SNAPSHOT_TREE_HEIGHT - 1);\n// ══════════════════════════════════ MESSAGE ══════════════════════════════════\n/// @dev See Header.sol: (uint8,uint32,uint32,uint32,uint32): 1+4+4+4+4\nuint256 constant HEADER_LENGTH = 17;\n/// @dev See Request.sol: (uint96,uint64,uint32): 12+8+4\nuint256 constant REQUEST_LENGTH = 24;\n/// @dev See Tips.sol: (uint64,uint64,uint64,uint64): 8+8+8+8\nuint256 constant TIPS_LENGTH = 32;\n/// @dev The amount of discarded last bits when encoding tip values\nuint256 constant TIPS_GRANULARITY = 32;\n/// @dev Tip values could be only the multiples of TIPS_MULTIPLIER\nuint256 constant TIPS_MULTIPLIER = 1 \u003c\u003c TIPS_GRANULARITY;\n// ══════════════════════════════ STATEMENT SALTS ══════════════════════════════\n/// @dev Salts for signing various statements\nbytes32 constant ATTESTATION_VALID_SALT = keccak256(\"ATTESTATION_VALID_SALT\");\nbytes32 constant ATTESTATION_INVALID_SALT = keccak256(\"ATTESTATION_INVALID_SALT\");\nbytes32 constant RECEIPT_VALID_SALT = keccak256(\"RECEIPT_VALID_SALT\");\nbytes32 constant RECEIPT_INVALID_SALT = keccak256(\"RECEIPT_INVALID_SALT\");\nbytes32 constant SNAPSHOT_VALID_SALT = keccak256(\"SNAPSHOT_VALID_SALT\");\nbytes32 constant STATE_INVALID_SALT = keccak256(\"STATE_INVALID_SALT\");\n// ═════════════════════════════════ PROTOCOL ══════════════════════════════════\n/// @dev Optimistic period for new agent roots in LightManager\nuint32 constant AGENT_ROOT_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Timeout between the agent root could be proposed and resolved in LightManager\nuint32 constant AGENT_ROOT_PROPOSAL_TIMEOUT = 12 hours;\nuint32 constant BONDING_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Amount of time that the Notary will not be considered active after they won a dispute\nuint32 constant DISPUTE_TIMEOUT_NOTARY = 12 hours;\n/// @dev Amount of time without fresh data from Notaries before contract owner can resolve stuck disputes manually\nuint256 constant FRESH_DATA_TIMEOUT = 4 hours;\n/// @dev Maximum bytes per message = 2 KiB (somewhat arbitrarily set to begin)\nuint256 constant MAX_CONTENT_BYTES = 2 * 2 ** 10;\n/// @dev Maximum value for the summit tip that could be set in GasOracle\nuint256 constant MAX_SUMMIT_TIP = 0.01 ether;\n\n// contracts/libs/Errors.sol\n\n// ══════════════════════════════ INVALID CALLER ═══════════════════════════════\n\nerror CallerNotAgentManager();\nerror CallerNotDestination();\nerror CallerNotInbox();\nerror CallerNotSummit();\n\n// ══════════════════════════════ INCORRECT DATA ═══════════════════════════════\n\nerror IncorrectAttestation();\nerror IncorrectAgentDomain();\nerror IncorrectAgentIndex();\nerror IncorrectAgentProof();\nerror IncorrectAgentRoot();\nerror IncorrectDataHash();\nerror IncorrectDestinationDomain();\nerror IncorrectOriginDomain();\nerror IncorrectSnapshotProof();\nerror IncorrectSnapshotRoot();\nerror IncorrectState();\nerror IncorrectStatesAmount();\nerror IncorrectTipsProof();\nerror IncorrectVersionLength();\n\nerror IncorrectNonce();\nerror IncorrectSender();\nerror IncorrectRecipient();\n\nerror FlagOutOfRange();\nerror IndexOutOfRange();\nerror NonceOutOfRange();\n\nerror OutdatedNonce();\n\nerror UnformattedAttestation();\nerror UnformattedAttestationReport();\nerror UnformattedBaseMessage();\nerror UnformattedCallData();\nerror UnformattedCallDataPrefix();\nerror UnformattedMessage();\nerror UnformattedReceipt();\nerror UnformattedReceiptReport();\nerror UnformattedSignature();\nerror UnformattedSnapshot();\nerror UnformattedState();\nerror UnformattedStateReport();\n\n// ═══════════════════════════════ MERKLE TREES ════════════════════════════════\n\nerror LeafNotProven();\nerror MerkleTreeFull();\nerror NotEnoughLeafs();\nerror TreeHeightTooLow();\n\n// ═════════════════════════════ OPTIMISTIC PERIOD ═════════════════════════════\n\nerror BaseClientOptimisticPeriod();\nerror MessageOptimisticPeriod();\nerror SlashAgentOptimisticPeriod();\nerror WithdrawTipsOptimisticPeriod();\nerror ZeroProofMaturity();\n\n// ═══════════════════════════════ AGENT MANAGER ═══════════════════════════════\n\nerror AgentNotGuard();\nerror AgentNotNotary();\n\nerror AgentCantBeAdded();\nerror AgentNotActive();\nerror AgentNotActiveNorUnstaking();\nerror AgentNotFraudulent();\nerror AgentNotUnstaking();\nerror AgentUnknown();\n\nerror AgentRootNotProposed();\nerror AgentRootTimeoutNotOver();\n\nerror NotStuck();\n\nerror DisputeAlreadyResolved();\nerror DisputeNotOpened();\nerror DisputeTimeoutNotOver();\nerror GuardInDispute();\nerror NotaryInDispute();\n\nerror MustBeSynapseDomain();\nerror SynapseDomainForbidden();\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\nerror AlreadyExecuted();\nerror AlreadyFailed();\nerror DuplicatedSnapshotRoot();\nerror IncorrectMagicValue();\nerror GasLimitTooLow();\nerror GasSuppliedTooLow();\n\n// ══════════════════════════════════ ORIGIN ═══════════════════════════════════\n\nerror ContentLengthTooBig();\nerror EthTransferFailed();\nerror InsufficientEthBalance();\n\n// ════════════════════════════════ GAS ORACLE ═════════════════════════════════\n\nerror LocalGasDataNotSet();\nerror RemoteGasDataNotSet();\n\n// ═══════════════════════════════════ TIPS ════════════════════════════════════\n\nerror SummitTipTooHigh();\nerror TipsClaimMoreThanEarned();\nerror TipsClaimZero();\nerror TipsOverflow();\nerror TipsValueTooLow();\n\n// ════════════════════════════════ MEMORY VIEW ════════════════════════════════\n\nerror IndexedTooMuch();\nerror ViewOverrun();\nerror OccupiedMemory();\nerror UnallocatedMemory();\nerror PrecompileOutOfGas();\n\n// ═════════════════════════════════ MULTICALL ═════════════════════════════════\n\nerror MulticallFailed();\n\n// contracts/libs/TypeCasts.sol\n\nlibrary TypeCasts {\n    // alignment preserving cast\n    function addressToBytes32(address addr) internal pure returns (bytes32) {\n        return bytes32(uint256(uint160(addr)));\n    }\n\n    // alignment preserving cast\n    function bytes32ToAddress(bytes32 buf) internal pure returns (address) {\n        return address(uint160(uint256(buf)));\n    }\n}\n\n// contracts/libs/stack/Number.sol\n\n/// Number is a compact representation of uint256, that is fit into 16 bits\n/// with the maximum relative error under 0.4%.\ntype Number is uint16;\n\nusing NumberLib for Number global;\n\n/// # Number\n/// Library for compact representation of uint256 numbers.\n/// - Number is stored using mantissa and exponent, each occupying 8 bits.\n/// - Numbers under 2**8 are stored as `mantissa` with `exponent = 0xFF`.\n/// - Numbers at least 2**8 are approximated as `(256 + mantissa) \u003c\u003c exponent`\n/// \u003e - `0 \u003c= mantissa \u003c 256`\n/// \u003e - `0 \u003c= exponent \u003c= 247` (`256 * 2**248` doesn't fit into uint256)\n/// # Number stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type  | Bytes |\n/// | ---------- | -------- | ----- | ----- |\n/// | (002..001] | mantissa | uint8 | 1     |\n/// | (001..000] | exponent | uint8 | 1     |\n\nlibrary NumberLib {\n    /// @dev Amount of bits to shift to mantissa field\n    uint16 private constant SHIFT_MANTISSA = 8;\n\n    /// @notice For bwad math (binary wad) we use 2**64 as \"wad\" unit.\n    /// @dev We are using not using 10**18 as wad, because it is not stored precisely in NumberLib.\n    uint256 internal constant BWAD_SHIFT = 64;\n    uint256 internal constant BWAD = 1 \u003c\u003c BWAD_SHIFT;\n    /// @notice ~0.1% in bwad units.\n    uint256 internal constant PER_MILLE_SHIFT = BWAD_SHIFT - 10;\n    uint256 internal constant PER_MILLE = 1 \u003c\u003c PER_MILLE_SHIFT;\n\n    /// @notice Compresses uint256 number into 16 bits.\n    function compress(uint256 value) internal pure returns (Number) {\n        // Find `msb` such as `2**msb \u003c= value \u003c 2**(msb + 1)`\n        uint256 msb = mostSignificantBit(value);\n        // We want to preserve 9 bits of precision.\n        // The highest bit is always 1, so we can skip it.\n        // The remaining 8 highest bits are stored as mantissa.\n        if (msb \u003c 8) {\n            // Value is less than 2**8, so we can use value as mantissa with \"-1\" exponent.\n            return _encode(uint8(value), 0xFF);\n        } else {\n            // We use `msb - 8` as exponent otherwise. Note that `exponent \u003e= 0`.\n            unchecked {\n                uint256 exponent = msb - 8;\n                // Shifting right by `msb-8` bits will shift the \"remaining 8 highest bits\" into the 8 lowest bits.\n                // uint8() will truncate the highest bit.\n                return _encode(uint8(value \u003e\u003e exponent), uint8(exponent));\n            }\n        }\n    }\n\n    /// @notice Decompresses 16 bits number into uint256.\n    /// @dev The outcome is an approximation of the original number: `(value - value / 256) \u003c number \u003c= value`.\n    function decompress(Number number) internal pure returns (uint256 value) {\n        // Isolate 8 highest bits as the mantissa.\n        uint256 mantissa = Number.unwrap(number) \u003e\u003e SHIFT_MANTISSA;\n        // This will truncate the highest bits, leaving only the exponent.\n        uint256 exponent = uint8(Number.unwrap(number));\n        if (exponent == 0xFF) {\n            return mantissa;\n        } else {\n            unchecked {\n                return (256 + mantissa) \u003c\u003c (exponent);\n            }\n        }\n    }\n\n    /// @dev Returns the most significant bit of `x`\n    /// https://solidity-by-example.org/bitwise/\n    function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\n        // To find `msb` we determine it bit by bit, starting from the highest one.\n        // `0 \u003c= msb \u003c= 255`, so we start from the highest bit, 1\u003c\u003c7 == 128.\n        // If `x` is at least 2**128, then the highest bit of `x` is at least 128.\n        // solhint-disable no-inline-assembly\n        assembly {\n            // `f` is set to 1\u003c\u003c7 if `x \u003e= 2**128` and to 0 otherwise.\n            let f := shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\n            // If `x \u003e= 2**128` then set `msb` highest bit to 1 and shift `x` right by 128.\n            // Otherwise, `msb` remains 0 and `x` remains unchanged.\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        // `x` is now at most 2**128 - 1. Continue the same way, the next highest bit is 1\u003c\u003c6 == 64.\n        assembly {\n            // `f` is set to 1\u003c\u003c6 if `x \u003e= 2**64` and to 0 otherwise.\n            let f := shl(6, gt(x, 0xFFFFFFFFFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c5 if `x \u003e= 2**32` and to 0 otherwise.\n            let f := shl(5, gt(x, 0xFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c4 if `x \u003e= 2**16` and to 0 otherwise.\n            let f := shl(4, gt(x, 0xFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c3 if `x \u003e= 2**8` and to 0 otherwise.\n            let f := shl(3, gt(x, 0xFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c2 if `x \u003e= 2**4` and to 0 otherwise.\n            let f := shl(2, gt(x, 0xF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c1 if `x \u003e= 2**2` and to 0 otherwise.\n            let f := shl(1, gt(x, 0x3))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1 if `x \u003e= 2**1` and to 0 otherwise.\n            let f := gt(x, 0x1)\n            msb := or(msb, f)\n        }\n    }\n\n    /// @dev Wraps (mantissa, exponent) pair into Number.\n    function _encode(uint8 mantissa, uint8 exponent) private pure returns (Number) {\n        // Casts below are upcasts, so they are safe.\n        return Number.wrap(uint16(mantissa) \u003c\u003c SHIFT_MANTISSA | uint16(exponent));\n    }\n}\n\n// contracts/libs/stack/Request.sol\n\n/// Request is encoded data with \"message execution request\".\ntype Request is uint192;\n\nusing RequestLib for Request global;\n\n/// Library for formatting _the request part_ of _the base messages_.\n/// - Request represents a message sender requirements for the message execution on the destination chain.\n/// - Request occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n/// \u003e gasDrop field is included for future compatibility and is ignored at the moment.\n///\n/// # Request stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type   | Bytes | Description                                          |\n/// | ---------- | -------- | ------ | ----- | ---------------------------------------------------- |\n/// | (024..012] | gasDrop  | uint96 | 12    | Minimum amount of gas token to drop to the recipient |\n/// | (012..004] | gasLimit | uint64 | 8     | Minimum amount of gas units to supply for execution  |\n/// | (004..000] | version  | uint32 | 4     | Base message version to pass to the recipient        |\n\nlibrary RequestLib {\n    /// @dev Amount of bits to shift to gasDrop field\n    uint192 private constant SHIFT_GAS_DROP = 12 * 8;\n    /// @dev Amount of bits to shift to gasLimit field\n    uint192 private constant SHIFT_GAS_LIMIT = 4 * 8;\n\n    /// @notice Returns an encoded request with the given fields\n    /// @param gasDrop_     Minimum amount of gas token to drop to the recipient (ignored at the moment)\n    /// @param gasLimit_    Minimum amount of gas units to supply for execution\n    /// @param version_     Base message version to pass to the recipient\n    function encodeRequest(uint96 gasDrop_, uint64 gasLimit_, uint32 version_) internal pure returns (Request) {\n        // Casts below are upcasts, so they are safe\n        return Request.wrap(uint192(gasDrop_) \u003c\u003c SHIFT_GAS_DROP | uint192(gasLimit_) \u003c\u003c SHIFT_GAS_LIMIT | version_);\n    }\n\n    /// @notice Wraps the padded encoded request into a Request-typed value.\n    /// @dev The \"padded\" request is simply an encoded request casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded requests\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedRequest) internal pure returns (Request) {\n        // Casting to uint192 will truncate the highest bits, which is the behavior we want\n        return Request.wrap(uint192(paddedRequest));\n    }\n\n    /// @notice Returns the requested of gas token to drop to the recipient.\n    function gasDrop(Request request) internal pure returns (uint96) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return uint96(Request.unwrap(request) \u003e\u003e SHIFT_GAS_DROP);\n    }\n\n    /// @notice Returns the requested minimum amount of gas units to supply for execution.\n    function gasLimit(Request request) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Request.unwrap(request) \u003e\u003e SHIFT_GAS_LIMIT);\n    }\n\n    /// @notice Returns the requested base message version to pass to the recipient.\n    function version(Request request) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Request.unwrap(request));\n    }\n}\n\n// node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        require(value \u003c= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        require(value \u003c= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        require(value \u003c= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value \u003c= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        require(value \u003c= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        require(value \u003c= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        require(value \u003c= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        require(value \u003c= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        require(value \u003c= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        require(value \u003c= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        require(value \u003c= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        require(value \u003c= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        require(value \u003c= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        require(value \u003c= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        require(value \u003c= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value \u003c= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        require(value \u003c= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        require(value \u003c= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        require(value \u003c= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value \u003c= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        require(value \u003c= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        require(value \u003c= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        require(value \u003c= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value \u003c= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        require(value \u003c= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        require(value \u003c= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        require(value \u003c= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value \u003c= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        require(value \u003c= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value \u003c= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value \u003c= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     *\n     * _Available since v3.0._\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value \u003e= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     *\n     * _Available since v3.0._\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value \u003c= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     *\n     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length \u003e 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance \u003e= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance \u003e= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length \u003e 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n\n// contracts/base/MultiCallable.sol\n\n/// @notice Collection of Multicall utilities. Fork of Multicall3:\n/// https://github.com/mds1/multicall/blob/master/src/Multicall3.sol\nabstract contract MultiCallable {\n    struct Call {\n        bool allowFailure;\n        bytes callData;\n    }\n\n    struct Result {\n        bool success;\n        bytes returnData;\n    }\n\n    /// @notice Aggregates a few calls to this contract into one multicall without modifying `msg.sender`.\n    function multicall(Call[] calldata calls) external returns (Result[] memory callResults) {\n        uint256 amount = calls.length;\n        callResults = new Result[](amount);\n        Call calldata call_;\n        for (uint256 i = 0; i \u003c amount;) {\n            call_ = calls[i];\n            Result memory result = callResults[i];\n            // We perform a delegate call to ourselves here. Delegate call does not modify `msg.sender`, so\n            // this will have the same effect as if `msg.sender` performed all the calls themselves one by one.\n            // solhint-disable-next-line avoid-low-level-calls\n            (result.success, result.returnData) = address(this).delegatecall(call_.callData);\n            // solhint-disable-next-line no-inline-assembly\n            assembly {\n                // Revert if the call fails and failure is not allowed\n                // `allowFailure := calldataload(call_)` and `success := mload(result)`\n                if iszero(or(calldataload(call_), mload(result))) {\n                    // Revert with `0x4d6a2328` (function selector for `MulticallFailed()`)\n                    mstore(0x00, 0x4d6a232800000000000000000000000000000000000000000000000000000000)\n                    revert(0x00, 0x04)\n                }\n            }\n            unchecked {\n                ++i;\n            }\n        }\n    }\n}\n\n// contracts/base/Version.sol\n\n/**\n * @title Versioned\n * @notice Version getter for contracts. Doesn't use any storage slots, meaning\n * it will never cause any troubles with the upgradeable contracts. For instance, this contract\n * can be added or removed from the inheritance chain without shifting the storage layout.\n */\nabstract contract Versioned {\n    /**\n     * @notice Struct that is mimicking the storage layout of a string with 32 bytes or less.\n     * Length is limited by 32, so the whole string payload takes two memory words:\n     * @param length    String length\n     * @param data      String characters\n     */\n    struct _ShortString {\n        uint256 length;\n        bytes32 data;\n    }\n\n    /// @dev Length of the \"version string\"\n    uint256 private immutable _length;\n    /// @dev Bytes representation of the \"version string\".\n    /// Strings with length over 32 are not supported!\n    bytes32 private immutable _data;\n\n    constructor(string memory version_) {\n        _length = bytes(version_).length;\n        if (_length \u003e 32) revert IncorrectVersionLength();\n        // bytes32 is left-aligned =\u003e this will store the byte representation of the string\n        // with the trailing zeroes to complete the 32-byte word\n        _data = bytes32(bytes(version_));\n    }\n\n    function version() external view returns (string memory versionString) {\n        // Load the immutable values to form the version string\n        _ShortString memory str = _ShortString(_length, _data);\n        // The only way to do this cast is doing some dirty assembly\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            versionString := str\n        }\n    }\n}\n\n// contracts/libs/ChainContext.sol\n\n/// @notice Library for accessing chain context variables as tightly packed integers.\n/// Messaging contracts should rely on this library for accessing chain context variables\n/// instead of doing the casting themselves.\nlibrary ChainContext {\n    using SafeCast for uint256;\n\n    /// @notice Returns the current block number as uint40.\n    /// @dev Reverts if block number is greater than 40 bits, which is not supposed to happen\n    /// until the block.timestamp overflows (assuming block time is at least 1 second).\n    function blockNumber() internal view returns (uint40) {\n        return block.number.toUint40();\n    }\n\n    /// @notice Returns the current block timestamp as uint40.\n    /// @dev Reverts if block timestamp is greater than 40 bits, which is\n    /// supposed to happen approximately in year 36835.\n    function blockTimestamp() internal view returns (uint40) {\n        return block.timestamp.toUint40();\n    }\n\n    /// @notice Returns the chain id as uint32.\n    /// @dev Reverts if chain id is greater than 32 bits, which is not\n    /// supposed to happen in production.\n    function chainId() internal view returns (uint32) {\n        return block.chainid.toUint32();\n    }\n}\n\n// contracts/libs/Structures.sol\n\n// Here we define common enums and structures to enable their easier reusing later.\n\n// ═══════════════════════════════ AGENT STATUS ════════════════════════════════\n\n/// @dev Potential statuses for the off-chain bonded agent:\n/// - Unknown: never provided a bond =\u003e signature not valid\n/// - Active: has a bond in BondingManager =\u003e signature valid\n/// - Unstaking: has a bond in BondingManager, initiated the unstaking =\u003e signature not valid\n/// - Resting: used to have a bond in BondingManager, successfully unstaked =\u003e signature not valid\n/// - Fraudulent: proven to commit fraud, value in Merkle Tree not updated =\u003e signature not valid\n/// - Slashed: proven to commit fraud, value in Merkle Tree was updated =\u003e signature not valid\n/// Unstaked agent could later be added back to THE SAME domain by staking a bond again.\n/// Honest agent: Unknown -\u003e Active -\u003e unstaking -\u003e Resting -\u003e Active ...\n/// Malicious agent: Unknown -\u003e Active -\u003e Fraudulent -\u003e Slashed\n/// Malicious agent: Unknown -\u003e Active -\u003e Unstaking -\u003e Fraudulent -\u003e Slashed\nenum AgentFlag {\n    Unknown,\n    Active,\n    Unstaking,\n    Resting,\n    Fraudulent,\n    Slashed\n}\n\n/// @notice Struct for storing an agent in the BondingManager contract.\nstruct AgentStatus {\n    AgentFlag flag;\n    uint32 domain;\n    uint32 index;\n}\n// 184 bits available for tight packing\n\nusing StructureUtils for AgentStatus global;\n\n/// @notice Potential statuses of an agent in terms of being in dispute\n/// - None: agent is not in dispute\n/// - Pending: agent is in unresolved dispute\n/// - Slashed: agent was in dispute that lead to agent being slashed\n/// Note: agent who won the dispute has their status reset to None\nenum DisputeFlag {\n    None,\n    Pending,\n    Slashed\n}\n\n/// @notice Struct for storing dispute status of an agent.\n/// @param flag         Dispute flag: None/Pending/Slashed.\n/// @param openedAt     Timestamp when the latest agent dispute was opened (zero if not opened).\n/// @param resolvedAt   Timestamp when the latest agent dispute was resolved (zero if not resolved).\nstruct DisputeStatus {\n    DisputeFlag flag;\n    uint40 openedAt;\n    uint40 resolvedAt;\n}\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\n/// @notice Struct representing the status of Destination contract.\n/// @param snapRootTime     Timestamp when latest snapshot root was accepted\n/// @param agentRootTime    Timestamp when latest agent root was accepted\n/// @param notaryIndex      Index of Notary who signed the latest agent root\nstruct DestinationStatus {\n    uint40 snapRootTime;\n    uint40 agentRootTime;\n    uint32 notaryIndex;\n}\n\n// ═══════════════════════════════ EXECUTION HUB ═══════════════════════════════\n\n/// @notice Potential statuses of the message in Execution Hub.\n/// - None: there hasn't been a valid attempt to execute the message yet\n/// - Failed: there was a valid attempt to execute the message, but recipient reverted\n/// - Success: there was a valid attempt to execute the message, and recipient did not revert\n/// Note: message can be executed until its status is Success\nenum MessageStatus {\n    None,\n    Failed,\n    Success\n}\n\nlibrary StructureUtils {\n    /// @notice Checks that Agent is Active\n    function verifyActive(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active) {\n            revert AgentNotActive();\n        }\n    }\n\n    /// @notice Checks that Agent is Unstaking\n    function verifyUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Unstaking) {\n            revert AgentNotUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Active or Unstaking\n    function verifyActiveUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active \u0026\u0026 status.flag != AgentFlag.Unstaking) {\n            revert AgentNotActiveNorUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Fraudulent\n    function verifyFraudulent(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Fraudulent) {\n            revert AgentNotFraudulent();\n        }\n    }\n\n    /// @notice Checks that Agent is not Unknown\n    function verifyKnown(AgentStatus memory status) internal pure {\n        if (status.flag == AgentFlag.Unknown) {\n            revert AgentUnknown();\n        }\n    }\n}\n\n// contracts/libs/memory/MemView.sol\n\n/// @dev MemView is an untyped view over a portion of memory to be used instead of `bytes memory`\ntype MemView is uint256;\n\n/// @dev Attach library functions to MemView\nusing MemViewLib for MemView global;\n\n/// @notice Library for operations with the memory views.\n/// Forked from https://github.com/summa-tx/memview-sol with several breaking changes:\n/// - The codebase is ported to Solidity 0.8\n/// - Custom errors are added\n/// - The runtime type checking is replaced with compile-time check provided by User-Defined Value Types\n///   https://docs.soliditylang.org/en/latest/types.html#user-defined-value-types\n/// - uint256 is used as the underlying type for the \"memory view\" instead of bytes29.\n///   It is wrapped into MemView custom type in order not to be confused with actual integers.\n/// - Therefore the \"type\" field is discarded, allowing to allocate 16 bytes for both view location and length\n/// - The documentation is expanded\n/// - Library functions unused by the rest of the codebase are removed\n//  - Very pretty code separators are added :)\nlibrary MemViewLib {\n    /// @notice Stack layout for uint256 (from highest bits to lowest)\n    /// (32 .. 16]      loc     16 bytes    Memory address of underlying bytes\n    /// (16 .. 00]      len     16 bytes    Length of underlying bytes\n\n    // ═══════════════════════════════════════════ BUILDING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Instantiate a new untyped memory view. This should generally not be called directly.\n     * Prefer `ref` wherever possible.\n     * @param loc_          The memory address\n     * @param len_          The length\n     * @return The new view with the specified location and length\n     */\n    function build(uint256 loc_, uint256 len_) internal pure returns (MemView) {\n        uint256 end_ = loc_ + len_;\n        // Make sure that a view is not constructed that points to unallocated memory\n        // as this could be indicative of a buffer overflow attack\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            if gt(end_, mload(0x40)) { end_ := 0 }\n        }\n        if (end_ == 0) {\n            revert UnallocatedMemory();\n        }\n        return _unsafeBuildUnchecked(loc_, len_);\n    }\n\n    /**\n     * @notice Instantiate a memory view from a byte array.\n     * @dev Note that due to Solidity memory representation, it is not possible to\n     * implement a deref, as the `bytes` type stores its len in memory.\n     * @param arr           The byte array\n     * @return The memory view over the provided byte array\n     */\n    function ref(bytes memory arr) internal pure returns (MemView) {\n        uint256 len_ = arr.length;\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 loc_;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // We add 0x20, so that the view starts exactly where the array data starts\n            loc_ := add(arr, 0x20)\n        }\n        return build(loc_, len_);\n    }\n\n    // ════════════════════════════════════════════ CLONING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to the new memory.\n     * @param memView       The memory view\n     * @return arr          The cloned byte array\n     */\n    function clone(MemView memView) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        unchecked {\n            _unsafeCopyTo(memView, ptr + 0x20);\n        }\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 len_ = memView.len();\n        uint256 footprint_ = memView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    /**\n     * @notice Copies all views, joins them into a new bytearray.\n     * @param memViews      The memory views\n     * @return arr          The new byte array with joined data behind the given views\n     */\n    function join(MemView[] memory memViews) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        MemView newView;\n        unchecked {\n            newView = _unsafeJoin(memViews, ptr + 0x20);\n        }\n        uint256 len_ = newView.len();\n        uint256 footprint_ = newView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    // ══════════════════════════════════════════ INSPECTING MEMORY VIEW ═══════════════════════════════════════════════\n\n    /**\n     * @notice Returns the memory address of the underlying bytes.\n     * @param memView       The memory view\n     * @return loc_         The memory address\n     */\n    function loc(MemView memView) internal pure returns (uint256 loc_) {\n        // loc is stored in the highest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u003e\u003e 128;\n    }\n\n    /**\n     * @notice Returns the number of bytes of the view.\n     * @param memView       The memory view\n     * @return len_         The length of the view\n     */\n    function len(MemView memView) internal pure returns (uint256 len_) {\n        // len is stored in the lowest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u0026 type(uint128).max;\n    }\n\n    /**\n     * @notice Returns the endpoint of `memView`.\n     * @param memView       The memory view\n     * @return end_         The endpoint of `memView`\n     */\n    function end(MemView memView) internal pure returns (uint256 end_) {\n        // The endpoint never overflows uint128, let alone uint256, so we could use unchecked math here\n        unchecked {\n            return memView.loc() + memView.len();\n        }\n    }\n\n    /**\n     * @notice Returns the number of memory words this memory view occupies, rounded up.\n     * @param memView       The memory view\n     * @return words_       The number of memory words\n     */\n    function words(MemView memView) internal pure returns (uint256 words_) {\n        // returning ceil(length / 32.0)\n        unchecked {\n            return (memView.len() + 31) \u003e\u003e 5;\n        }\n    }\n\n    /**\n     * @notice Returns the in-memory footprint of a fresh copy of the view.\n     * @param memView       The memory view\n     * @return footprint_   The in-memory footprint of a fresh copy of the view.\n     */\n    function footprint(MemView memView) internal pure returns (uint256 footprint_) {\n        // words() * 32\n        return memView.words() \u003c\u003c 5;\n    }\n\n    // ════════════════════════════════════════════ HASHING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the keccak256 hash of the underlying memory\n     * @param memView       The memory view\n     * @return digest       The keccak256 hash of the underlying memory\n     */\n    function keccak(MemView memView) internal pure returns (bytes32 digest) {\n        uint256 loc_ = memView.loc();\n        uint256 len_ = memView.len();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            digest := keccak256(loc_, len_)\n        }\n    }\n\n    /**\n     * @notice Adds a salt to the keccak256 hash of the underlying data and returns the keccak256 hash of the\n     * resulting data.\n     * @param memView       The memory view\n     * @return digestSalted keccak256(salt, keccak256(memView))\n     */\n    function keccakSalted(MemView memView, bytes32 salt) internal pure returns (bytes32 digestSalted) {\n        return keccak256(bytes.concat(salt, memView.keccak()));\n    }\n\n    // ════════════════════════════════════════════ SLICING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Safe slicing without memory modification.\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the given index\n     */\n    function slice(MemView memView, uint256 index_, uint256 len_) internal pure returns (MemView) {\n        uint256 loc_ = memView.loc();\n        // Ensure it doesn't overrun the view\n        if (loc_ + index_ + len_ \u003e memView.end()) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // loc_ + index_ \u003c= memView.end()\n            return build({loc_: loc_ + index_, len_: len_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing bytes from `index` to end(memView).\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @return The new view for the slice starting from the given index until the initial view endpoint\n     */\n    function sliceFrom(MemView memView, uint256 index_) internal pure returns (MemView) {\n        uint256 len_ = memView.len();\n        // Ensure it doesn't overrun the view\n        if (index_ \u003e len_) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // index_ \u003c= len_ =\u003e memView.loc() + index_ \u003c= memView.loc() + memView.len() == memView.end()\n            return build({loc_: memView.loc() + index_, len_: len_ - index_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the first `len` bytes.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the initial view beginning\n     */\n    function prefix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        return memView.slice({index_: 0, len_: len_});\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the last `len` byte.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length until the initial view endpoint\n     */\n    function postfix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        uint256 viewLen = memView.len();\n        // Ensure it doesn't overrun the view\n        if (len_ \u003e viewLen) {\n            revert ViewOverrun();\n        }\n        // Could do the unchecked math due to the check above\n        uint256 index_;\n        unchecked {\n            index_ = viewLen - len_;\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // len_ \u003c= memView.len() =\u003e memView.loc() \u003c= loc_ \u003c= memView.end()\n            return build({loc_: memView.loc() + viewLen - len_, len_: len_});\n        }\n    }\n\n    // ═══════════════════════════════════════════ INDEXING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Load up to 32 bytes from the view onto the stack.\n     * @dev Returns a bytes32 with only the `bytes_` HIGHEST bytes set.\n     * This can be immediately cast to a smaller fixed-length byte array.\n     * To automatically cast to an integer, use `indexUint`.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return result       The 32 byte result having only `bytes_` highest bytes set\n     */\n    function index(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (bytes32 result) {\n        if (bytes_ == 0) {\n            return bytes32(0);\n        }\n        // Can't load more than 32 bytes to the stack in one go\n        if (bytes_ \u003e 32) {\n            revert IndexedTooMuch();\n        }\n        // The last indexed byte should be within view boundaries\n        if (index_ + bytes_ \u003e memView.len()) {\n            revert ViewOverrun();\n        }\n        uint256 bitLength = bytes_ \u003c\u003c 3; // bytes_ * 8\n        uint256 loc_ = memView.loc();\n        // Get a mask with `bitLength` highest bits set\n        uint256 mask;\n        // 0x800...00 binary representation is 100...00\n        // sar stands for \"signed arithmetic shift\": https://en.wikipedia.org/wiki/Arithmetic_shift\n        // sar(N-1, 100...00) = 11...100..00, with exactly N highest bits set to 1\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            mask := sar(sub(bitLength, 1), 0x8000000000000000000000000000000000000000000000000000000000000000)\n        }\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load a full word using index offset, and apply mask to ignore non-relevant bytes\n            result := and(mload(add(loc_, index_)), mask)\n        }\n    }\n\n    /**\n     * @notice Parse an unsigned integer from the view at `index`.\n     * @dev Requires that the view have \u003e= `bytes_` bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return The unsigned integer\n     */\n    function indexUint(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (uint256) {\n        bytes32 indexedBytes = memView.index(index_, bytes_);\n        // `index()` returns left-aligned `bytes_`, while integers are right-aligned\n        // Shifting here to right-align with the full 32 bytes word: need to shift right `(32 - bytes_)` bytes\n        unchecked {\n            // memView.index() reverts when bytes_ \u003e 32, thus unchecked math\n            return uint256(indexedBytes) \u003e\u003e ((32 - bytes_) \u003c\u003c 3);\n        }\n    }\n\n    /**\n     * @notice Parse an address from the view at `index`.\n     * @dev Requires that the view have \u003e= 20 bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @return The address\n     */\n    function indexAddress(MemView memView, uint256 index_) internal pure returns (address) {\n        // index 20 bytes as `uint160`, and then cast to `address`\n        return address(uint160(memView.indexUint(index_, 20)));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns a memory view over the specified memory location\n    /// without checking if it points to unallocated memory.\n    function _unsafeBuildUnchecked(uint256 loc_, uint256 len_) private pure returns (MemView) {\n        // There is no scenario where loc or len would overflow uint128, so we omit this check.\n        // We use the highest 128 bits to encode the location and the lowest 128 bits to encode the length.\n        return MemView.wrap((loc_ \u003c\u003c 128) | len_);\n    }\n\n    /**\n     * @notice Copy the view to a location, return an unsafe memory reference\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memView       The memory view\n     * @param newLoc        The new location to copy the underlying view data\n     * @return The memory view over the unsafe memory with the copied underlying data\n     */\n    function _unsafeCopyTo(MemView memView, uint256 newLoc) private view returns (MemView) {\n        uint256 len_ = memView.len();\n        uint256 oldLoc = memView.loc();\n\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (newLoc \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        bool res;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // use the identity precompile (0x04) to copy\n            res := staticcall(gas(), 0x04, oldLoc, len_, newLoc, len_)\n        }\n        if (!res) revert PrecompileOutOfGas();\n        return _unsafeBuildUnchecked({loc_: newLoc, len_: len_});\n    }\n\n    /**\n     * @notice Join the views in memory, return an unsafe reference to the memory.\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memViews      The memory views\n     * @return The conjoined view pointing to the new memory\n     */\n    function _unsafeJoin(MemView[] memory memViews, uint256 location) private view returns (MemView) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (location \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        // Copy the views to the specified location one by one, by tracking the amount of copied bytes so far\n        uint256 offset = 0;\n        for (uint256 i = 0; i \u003c memViews.length;) {\n            MemView memView = memViews[i];\n            // We can use the unchecked math here as location + sum(view.length) will never overflow uint256\n            unchecked {\n                _unsafeCopyTo(memView, location + offset);\n                offset += memView.len();\n                ++i;\n            }\n        }\n        return _unsafeBuildUnchecked({loc_: location, len_: offset});\n    }\n}\n\n// contracts/libs/merkle/MerkleMath.sol\n\nlibrary MerkleMath {\n    // ═════════════════════════════════════════ BASIC MERKLE CALCULATIONS ═════════════════════════════════════════════\n\n    /**\n     * @notice Calculates the merkle root for the given leaf and merkle proof.\n     * @dev Will revert if proof length exceeds the tree height.\n     * @param index     Index of `leaf` in tree\n     * @param leaf      Leaf of the merkle tree\n     * @param proof     Proof of inclusion of `leaf` in the tree\n     * @param height    Height of the merkle tree\n     * @return root_    Calculated Merkle Root\n     */\n    function proofRoot(uint256 index, bytes32 leaf, bytes32[] memory proof, uint256 height)\n        internal\n        pure\n        returns (bytes32 root_)\n    {\n        // Proof length could not exceed the tree height\n        uint256 proofLen = proof.length;\n        if (proofLen \u003e height) revert TreeHeightTooLow();\n        root_ = leaf;\n        /// @dev Apply unchecked to all ++h operations\n        unchecked {\n            // Go up the tree levels from the leaf following the proof\n            for (uint256 h = 0; h \u003c proofLen; ++h) {\n                // Get a sibling node on current level: this is proof[h]\n                root_ = getParent(root_, proof[h], index, h);\n            }\n            // Go up to the root: the remaining siblings are EMPTY\n            for (uint256 h = proofLen; h \u003c height; ++h) {\n                root_ = getParent(root_, bytes32(0), index, h);\n            }\n        }\n    }\n\n    /**\n     * @notice Calculates the parent of a node on the path from one of the leafs to root.\n     * @param node          Node on a path from tree leaf to root\n     * @param sibling       Sibling for a given node\n     * @param leafIndex     Index of the tree leaf\n     * @param nodeHeight    \"Level height\" for `node` (ZERO for leafs, ORIGIN_TREE_HEIGHT for root)\n     */\n    function getParent(bytes32 node, bytes32 sibling, uint256 leafIndex, uint256 nodeHeight)\n        internal\n        pure\n        returns (bytes32 parent)\n    {\n        // Index for `node` on its \"tree level\" is (leafIndex / 2**height)\n        // \"Left child\" has even index, \"right child\" has odd index\n        if ((leafIndex \u003e\u003e nodeHeight) \u0026 1 == 0) {\n            // Left child\n            return getParent(node, sibling);\n        } else {\n            // Right child\n            return getParent(sibling, node);\n        }\n    }\n\n    /// @notice Calculates the parent of tow nodes in the merkle tree.\n    /// @dev We use implementation with H(0,0) = 0\n    /// This makes EVERY empty node in the tree equal to ZERO,\n    /// saving us from storing H(0,0), H(H(0,0), H(0, 0)), and so on\n    /// @param leftChild    Left child of the calculated node\n    /// @param rightChild   Right child of the calculated node\n    /// @return parent      Value for the node having above mentioned children\n    function getParent(bytes32 leftChild, bytes32 rightChild) internal pure returns (bytes32 parent) {\n        if (leftChild == bytes32(0) \u0026\u0026 rightChild == bytes32(0)) {\n            return 0;\n        } else {\n            return keccak256(bytes.concat(leftChild, rightChild));\n        }\n    }\n\n    // ════════════════════════════════ ROOT/PROOF CALCULATION FOR A LIST OF LEAFS ═════════════════════════════════════\n\n    /**\n     * @notice Calculates merkle root for a list of given leafs.\n     * Merkle Tree is constructed by padding the list with ZERO values for leafs until list length is `2**height`.\n     * Merkle Root is calculated for the constructed tree, and then saved in `leafs[0]`.\n     * \u003e Note:\n     * \u003e - `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * \u003e - Caller is expected not to reuse `hashes` list after the call, and only use `leafs[0]` value,\n     * which is guaranteed to contain the calculated merkle root.\n     * \u003e - root is calculated using the `H(0,0) = 0` Merkle Tree implementation. See MerkleTree.sol for details.\n     * @dev Amount of leaves should be at most `2**height`\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param height    Height of the Merkle Tree to construct\n     */\n    function calculateRoot(bytes32[] memory hashes, uint256 height) internal pure {\n        uint256 levelLength = hashes.length;\n        // Amount of hashes could not exceed amount of leafs in tree with the given height\n        if (levelLength \u003e (1 \u003c\u003c height)) revert TreeHeightTooLow();\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\": the amount of iterations for the for loop above.\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n            }\n        }\n    }\n\n    /**\n     * @notice Generates a proof of inclusion of a leaf in the list. If the requested index is outside\n     * of the list range, generates a proof of inclusion for an empty leaf (proof of non-inclusion).\n     * The Merkle Tree is constructed by padding the list with ZERO values until list length is a power of two\n     * __AND__ index is in the extended list range. For example:\n     *  - `hashes.length == 6` and `0 \u003c= index \u003c= 7` will \"extend\" the list to 8 entries.\n     *  - `hashes.length == 6` and `7 \u003c index \u003c= 15` will \"extend\" the list to 16 entries.\n     * \u003e Note: `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * Caller is expected not to reuse `hashes` list after the call.\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param index     Leaf index to generate the proof for\n     * @return proof    Generated merkle proof\n     */\n    function calculateProof(bytes32[] memory hashes, uint256 index) internal pure returns (bytes32[] memory proof) {\n        // Use only meaningful values for the shortened proof\n        // Check if index is within the list range (we want to generates proofs for outside leafs as well)\n        uint256 height = getHeight(index \u003c hashes.length ? hashes.length : (index + 1));\n        proof = new bytes32[](height);\n        uint256 levelLength = hashes.length;\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Use sibling for the merkle proof; `index^1` is index of our sibling\n                proof[h] = (index ^ 1 \u003c levelLength) ? hashes[index ^ 1] : bytes32(0);\n\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\"\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n                // Traverse to parent node\n                index \u003e\u003e= 1;\n            }\n        }\n    }\n\n    /// @notice Returns the height of the tree having a given amount of leafs.\n    function getHeight(uint256 leafs) internal pure returns (uint256 height) {\n        uint256 amount = 1;\n        while (amount \u003c leafs) {\n            unchecked {\n                ++height;\n            }\n            amount \u003c\u003c= 1;\n        }\n    }\n}\n\n// contracts/libs/stack/GasData.sol\n\n/// GasData in encoded data with \"basic information about gas prices\" for some chain.\ntype GasData is uint96;\n\nusing GasDataLib for GasData global;\n\n/// ChainGas is encoded data with given chain's \"basic information about gas prices\".\ntype ChainGas is uint128;\n\nusing GasDataLib for ChainGas global;\n\n/// Library for encoding and decoding GasData and ChainGas structs.\n/// # GasData\n/// `GasData` is a struct to store the \"basic information about gas prices\", that could\n/// be later used to approximate the cost of a message execution, and thus derive the\n/// minimal tip values for sending a message to the chain.\n/// \u003e - `GasData` is supposed to be cached by `GasOracle` contract, allowing to store the\n/// \u003e approximates instead of the exact values, and thus save on storage costs.\n/// \u003e - For instance, if `GasOracle` only updates the values on +- 10% change, having an\n/// \u003e 0.4% error on the approximates would be acceptable.\n/// `GasData` is supposed to be included in the Origin's state, which are synced across\n/// chains using Agent-signed snapshots and attestations.\n/// ## GasData stack layout (from highest bits to lowest)\n///\n/// | Position   | Field        | Type   | Bytes | Description                                         |\n/// | ---------- | ------------ | ------ | ----- | --------------------------------------------------- |\n/// | (012..010] | gasPrice     | uint16 | 2     | Gas price for the chain (in Wei per gas unit)       |\n/// | (010..008] | dataPrice    | uint16 | 2     | Calldata price (in Wei per byte of content)         |\n/// | (008..006] | execBuffer   | uint16 | 2     | Tx fee safety buffer for message execution (in Wei) |\n/// | (006..004] | amortAttCost | uint16 | 2     | Amortized cost for attestation submission (in Wei)  |\n/// | (004..002] | etherPrice   | uint16 | 2     | Chain's Ether Price / Mainnet Ether Price (in BWAD) |\n/// | (002..000] | markup       | uint16 | 2     | Markup for the message execution (in BWAD)          |\n/// \u003e See Number.sol for more details on `Number` type and BWAD (binary WAD) math.\n///\n/// ## ChainGas stack layout (from highest bits to lowest)\n///\n/// | Position   | Field   | Type   | Bytes | Description      |\n/// | ---------- | ------- | ------ | ----- | ---------------- |\n/// | (016..004] | gasData | uint96 | 12    | Chain's gas data |\n/// | (004..000] | domain  | uint32 | 4     | Chain's domain   |\nlibrary GasDataLib {\n    /// @dev Amount of bits to shift to gasPrice field\n    uint96 private constant SHIFT_GAS_PRICE = 10 * 8;\n    /// @dev Amount of bits to shift to dataPrice field\n    uint96 private constant SHIFT_DATA_PRICE = 8 * 8;\n    /// @dev Amount of bits to shift to execBuffer field\n    uint96 private constant SHIFT_EXEC_BUFFER = 6 * 8;\n    /// @dev Amount of bits to shift to amortAttCost field\n    uint96 private constant SHIFT_AMORT_ATT_COST = 4 * 8;\n    /// @dev Amount of bits to shift to etherPrice field\n    uint96 private constant SHIFT_ETHER_PRICE = 2 * 8;\n\n    /// @dev Amount of bits to shift to gasData field\n    uint128 private constant SHIFT_GAS_DATA = 4 * 8;\n\n    // ═════════════════════════════════════════════════ GAS DATA ══════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded GasData struct with the given fields.\n    /// @param gasPrice_        Gas price for the chain (in Wei per gas unit)\n    /// @param dataPrice_       Calldata price (in Wei per byte of content)\n    /// @param execBuffer_      Tx fee safety buffer for message execution (in Wei)\n    /// @param amortAttCost_    Amortized cost for attestation submission (in Wei)\n    /// @param etherPrice_      Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n    /// @param markup_          Markup for the message execution (in BWAD)\n    function encodeGasData(\n        Number gasPrice_,\n        Number dataPrice_,\n        Number execBuffer_,\n        Number amortAttCost_,\n        Number etherPrice_,\n        Number markup_\n    ) internal pure returns (GasData) {\n        // Number type wraps uint16, so could safely be casted to uint96\n        // forgefmt: disable-next-item\n        return GasData.wrap(\n            uint96(Number.unwrap(gasPrice_)) \u003c\u003c SHIFT_GAS_PRICE |\n            uint96(Number.unwrap(dataPrice_)) \u003c\u003c SHIFT_DATA_PRICE |\n            uint96(Number.unwrap(execBuffer_)) \u003c\u003c SHIFT_EXEC_BUFFER |\n            uint96(Number.unwrap(amortAttCost_)) \u003c\u003c SHIFT_AMORT_ATT_COST |\n            uint96(Number.unwrap(etherPrice_)) \u003c\u003c SHIFT_ETHER_PRICE |\n            uint96(Number.unwrap(markup_))\n        );\n    }\n\n    /// @notice Wraps padded uint256 value into GasData struct.\n    function wrapGasData(uint256 paddedGasData) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(paddedGasData));\n    }\n\n    /// @notice Returns the gas price, in Wei per gas unit.\n    function gasPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_GAS_PRICE));\n    }\n\n    /// @notice Returns the calldata price, in Wei per byte of content.\n    function dataPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_DATA_PRICE));\n    }\n\n    /// @notice Returns the tx fee safety buffer for message execution, in Wei.\n    function execBuffer(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_EXEC_BUFFER));\n    }\n\n    /// @notice Returns the amortized cost for attestation submission, in Wei.\n    function amortAttCost(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_AMORT_ATT_COST));\n    }\n\n    /// @notice Returns the ratio of Chain's Ether Price / Mainnet Ether Price, in BWAD math.\n    function etherPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_ETHER_PRICE));\n    }\n\n    /// @notice Returns the markup for the message execution, in BWAD math.\n    function markup(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data)));\n    }\n\n    // ════════════════════════════════════════════════ CHAIN DATA ═════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded ChainGas struct with the given fields.\n    /// @param gasData_ Chain's gas data\n    /// @param domain_  Chain's domain\n    function encodeChainGas(GasData gasData_, uint32 domain_) internal pure returns (ChainGas) {\n        // GasData type wraps uint96, so could safely be casted to uint128\n        return ChainGas.wrap(uint128(GasData.unwrap(gasData_)) \u003c\u003c SHIFT_GAS_DATA | uint128(domain_));\n    }\n\n    /// @notice Wraps padded uint256 value into ChainGas struct.\n    function wrapChainGas(uint256 paddedChainGas) internal pure returns (ChainGas) {\n        // Casting to uint128 will truncate the highest bits, which is the behavior we want\n        return ChainGas.wrap(uint128(paddedChainGas));\n    }\n\n    /// @notice Returns the chain's gas data.\n    function gasData(ChainGas data) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(ChainGas.unwrap(data) \u003e\u003e SHIFT_GAS_DATA));\n    }\n\n    /// @notice Returns the chain's domain.\n    function domain(ChainGas data) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(ChainGas.unwrap(data));\n    }\n\n    /// @notice Returns the hash for the list of ChainGas structs.\n    function snapGasHash(ChainGas[] memory snapGas) internal pure returns (bytes32 snapGasHash_) {\n        // Use assembly to calculate the hash of the array without copying it\n        // ChainGas takes a single word of storage, thus ChainGas[] is stored in the following way:\n        // 0x00: length of the array, in words\n        // 0x20: first ChainGas struct\n        // 0x40: second ChainGas struct\n        // And so on...\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Find the location where the array data starts, we add 0x20 to skip the length field\n            let loc := add(snapGas, 0x20)\n            // Load the length of the array (in words).\n            // Shifting left 5 bits is equivalent to multiplying by 32: this converts from words to bytes.\n            let len := shl(5, mload(snapGas))\n            // Calculate the hash of the array\n            snapGasHash_ := keccak256(loc, len)\n        }\n    }\n}\n\n// contracts/libs/stack/Header.sol\n\n/// Header is encoded data with \"general routing information\".\ntype Header is uint136;\n\nusing HeaderLib for Header global;\n\n/// Types of messages supported by Origin-Destination\n/// - Base: message sent by protocol user, contains tips\n/// - Manager: message sent between AgentManager contracts located on different chains, no tips\nenum MessageFlag {\n    Base,\n    Manager\n}\n\nusing HeaderLib for MessageFlag global;\n\n/// Library for formatting _the header part_ of _the messages used by Origin and Destination_.\n/// - Header represents general information for routing a Message for Origin and Destination.\n/// - Header occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n///\n/// # Header stack layout (from highest bits to lowest)\n///\n/// | Position   | Field            | Type   | Bytes | Description                             |\n/// | ---------- | ---------------- | ------ | ----- | --------------------------------------- |\n/// | (017..016] | flag             | uint8  | 1     | Flag specifying the type of message     |\n/// | (016..012] | origin           | uint32 | 4     | Domain where message originated         |\n/// | (012..008] | nonce            | uint32 | 4     | Message nonce on the origin domain      |\n/// | (008..004] | destination      | uint32 | 4     | Domain where message will be executed   |\n/// | (004..000] | optimisticPeriod | uint32 | 4     | Optimistic period that will be enforced |\nlibrary HeaderLib {\n    /// @dev Amount of bits to shift to flag field\n    uint136 private constant SHIFT_FLAG = 16 * 8;\n    /// @dev Amount of bits to shift to origin field\n    uint136 private constant SHIFT_ORIGIN = 12 * 8;\n    /// @dev Amount of bits to shift to nonce field\n    uint136 private constant SHIFT_NONCE = 8 * 8;\n    /// @dev Amount of bits to shift to destination field\n    uint136 private constant SHIFT_DESTINATION = 4 * 8;\n\n    /// @notice Returns an encoded header with provided fields\n    /// @param origin_              Domain of origin chain\n    /// @param nonce_               Message nonce on origin chain\n    /// @param destination_         Domain of destination chain\n    /// @param optimisticPeriod_    Optimistic period for message execution\n    function encodeHeader(\n        MessageFlag flag_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint32 destination_,\n        uint32 optimisticPeriod_\n    ) internal pure returns (Header) {\n        // All casts below are upcasts, so they are safe\n        // forgefmt: disable-next-item\n        return Header.wrap(\n            uint136(uint8(flag_)) \u003c\u003c SHIFT_FLAG |\n            uint136(origin_) \u003c\u003c SHIFT_ORIGIN |\n            uint136(nonce_) \u003c\u003c SHIFT_NONCE |\n            uint136(destination_) \u003c\u003c SHIFT_DESTINATION |\n            uint136(optimisticPeriod_)\n        );\n    }\n\n    /// @notice Checks that the header is a valid encoded header.\n    function isHeader(uint256 paddedHeader) internal pure returns (bool) {\n        // Check that flag is within range\n        return _flag(paddedHeader) \u003c= uint8(type(MessageFlag).max);\n    }\n\n    /// @notice Wraps the padded encoded request into a Header-typed value.\n    /// @dev The \"padded\" header is simply an encoded header casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded headers\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedHeader) internal pure returns (Header) {\n        // Check that flag is within range\n        if (!isHeader(paddedHeader)) revert FlagOutOfRange();\n        // Casting to uint136 will truncate the highest bits, which is the behavior we want\n        return Header.wrap(uint136(paddedHeader));\n    }\n\n    /// @notice Returns header's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Header header) internal pure returns (bytes32 hashedHeader) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store header in scratch space\n            mstore(0, header)\n            // Compute hash of header padded to 32 bytes\n            hashedHeader := keccak256(0, 32)\n        }\n    }\n\n    // ══════════════════════════════════════════════ HEADER SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns header's flag field\n    function flag(Header header) internal pure returns (MessageFlag) {\n        // We check that flag is within range when wrapping the header, so this cast is safe\n        return MessageFlag(_flag(Header.unwrap(header)));\n    }\n\n    /// @notice Returns header's origin field\n    function origin(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_ORIGIN);\n    }\n\n    /// @notice Returns header's nonce field\n    function nonce(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_NONCE);\n    }\n\n    /// @notice Returns header's destination field\n    function destination(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_DESTINATION);\n    }\n\n    /// @notice Returns header's optimistic seconds field\n    function optimisticPeriod(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns header's flag field without casting to MessageFlag\n    function _flag(uint256 paddedHeader) private pure returns (uint8) {\n        // Casting to uint8 will truncate the highest bits, which is the behavior we want\n        return uint8(paddedHeader \u003e\u003e SHIFT_FLAG);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n     * constructor.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall \u0026\u0026 _initialized \u003c 1) || (!AddressUpgradeable.isContract(address(this)) \u0026\u0026 _initialized == 1),\n            \"Initializable: contract is already initialized\"\n        );\n        _initialized = 1;\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: setting the version to 255 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing \u0026\u0026 _initialized \u003c version, \"Initializable: contract is already initialized\");\n        _initialized = version;\n        _initializing = true;\n        _;\n        _initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        require(_initializing, \"Initializable: contract is not initializing\");\n        _;\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized != type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint8) {\n        return _initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _initializing;\n    }\n}\n\n// contracts/interfaces/IAgentManager.sol\n\ninterface IAgentManager {\n    /**\n     * @notice Allows Inbox to open a Dispute between a Guard and a Notary, if they are both not in Dispute already.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Guard or Notary is already in Dispute.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Allows Inbox to slash an agent, if their fraud was proven.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Domain doesn't match the saved agent domain.\n     * @param domain    Domain where the Agent is active\n     * @param agent     Address of the Agent\n     * @param prover    Address that initially provided fraud proof\n     */\n    function slashAgent(uint32 domain, address agent, address prover) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest known root of the Agent Merkle Tree.\n     */\n    function agentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns the number of opened Disputes.\n     * @dev This includes the Disputes that have been resolved already.\n     */\n    function getDisputesAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns information about the dispute with the given index.\n     * @dev Will revert if dispute with given index hasn't been opened yet.\n     * @param index             Dispute index\n     * @return guard            Address of the Guard in the Dispute\n     * @return notary           Address of the Notary in the Dispute\n     * @return slashedAgent     Address of the Agent who was slashed when Dispute was resolved\n     * @return fraudProver      Address who provided fraud proof to resolve the Dispute\n     * @return reportPayload    Raw payload with report data that led to the Dispute\n     * @return reportSignature  Guard signature for the report payload\n     */\n    function getDispute(uint256 index)\n        external\n        view\n        returns (\n            address guard,\n            address notary,\n            address slashedAgent,\n            address fraudProver,\n            bytes memory reportPayload,\n            bytes memory reportSignature\n        );\n\n    /**\n     * @notice Returns the current Dispute status of a given agent. See Structures.sol for details.\n     * @dev Every returned value will be set to zero if agent was not slashed and is not in Dispute.\n     * `rival` and `disputePtr` will be set to zero if the agent was slashed without being in Dispute.\n     * @param agent         Agent address\n     * @return flag         Flag describing the current Dispute status for the agent: None/Pending/Slashed\n     * @return rival        Address of the rival agent in the Dispute\n     * @return fraudProver  Address who provided fraud proof to resolve the Dispute\n     * @return disputePtr   Index of the opened Dispute PLUS ONE. Zero if agent is not in Dispute.\n     */\n    function disputeStatus(address agent)\n        external\n        view\n        returns (DisputeFlag flag, address rival, address fraudProver, uint256 disputePtr);\n}\n\n// contracts/interfaces/IAgentSecured.sol\n\ninterface IAgentSecured {\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * between a Guard and a Notary has been opened.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * has been resolved due to one of the agents being slashed.\n     * \u003e `rivalIndex` will be ZERO, if the slashed agent was not in the Dispute.\n     * @param slashedIndex  Index of the slashed agent in the Agent Merkle Tree\n     * @param rivalIndex    Index of the their Dispute Rival in the Agent Merkle Tree\n     */\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the address of the local AgentManager contract, which is treated as\n     * the \"source of truth\" for agent statuses.\n     */\n    function agentManager() external view returns (address);\n\n    /**\n     * @notice Returns the address of the local Inbox contract, which is treated as\n     * the \"source of truth\" for agent-signed statements.\n     * @dev Inbox passes verified agent statements to `IAgentSecured` contract.\n     */\n    function inbox() external view returns (address);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns (flag, openedAt, resolvedAt) that describes the latest status of\n     * the latest dispute for an agent with a given index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param agentIndex    Agent index in the Agent Merkle Tree\n     * @return              Latest dispute status for the given agent: (flag, openedAt, resolvedAt)\n     */\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory);\n}\n\n// contracts/libs/memory/ByteString.sol\n\n/// @dev CallData is a memory view over the payload to be used for an external call, i.e.\n/// recipient.call(callData). Its length is always (4 + 32 * N) bytes:\n/// - First 4 bytes represent the function selector.\n/// - 32 * N bytes represent N words that function arguments occupy.\ntype CallData is uint256;\n\n/// @dev Attach library functions to CallData\nusing ByteString for CallData global;\n\n/// @dev Signature is a memory view over a \"65 bytes\" array representing a ECDSA signature.\ntype Signature is uint256;\n\n/// @dev Attach library functions to Signature\nusing ByteString for Signature global;\n\nlibrary ByteString {\n    using MemViewLib for bytes;\n\n    /**\n     * @dev non-compact ECDSA signatures are enforced as of OZ 4.7.3\n     *\n     *      Signature payload memory layout\n     * [000 .. 032) r   bytes32 32 bytes\n     * [032 .. 064) s   bytes32 32 bytes\n     * [064 .. 065) v   uint8    1 byte\n     */\n    uint256 internal constant SIGNATURE_LENGTH = 65;\n    uint256 private constant OFFSET_R = 0;\n    uint256 private constant OFFSET_S = 32;\n    uint256 private constant OFFSET_V = 64;\n\n    /**\n     * @dev Calldata memory layout\n     * [000 .. 004) selector    bytes4  4 bytes\n     *      Optional: N function arguments\n     * [004 .. 036) arg1        bytes32 32 bytes\n     *      ..\n     * [AAA .. END) argN        bytes32 32 bytes\n     */\n    uint256 internal constant SELECTOR_LENGTH = 4;\n    uint256 private constant OFFSET_SELECTOR = 0;\n    uint256 private constant OFFSET_ARGUMENTS = SELECTOR_LENGTH;\n\n    // ═════════════════════════════════════════════════ SIGNATURE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the signature payload from the given values.\n     * @dev Using ByteString.formatSignature({r: r, s: s, v: v}) will make sure\n     * that params are given in the right order.\n     */\n    function formatSignature(bytes32 r, bytes32 s, uint8 v) internal pure returns (bytes memory) {\n        return abi.encodePacked(r, s, v);\n    }\n\n    /**\n     * @notice Returns a Signature view over for the given payload.\n     * @dev Will revert if the payload is not a signature.\n     */\n    function castToSignature(bytes memory payload) internal pure returns (Signature) {\n        return castToSignature(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Signature view.\n     * @dev Will revert if the memory view is not over a signature.\n     */\n    function castToSignature(MemView memView) internal pure returns (Signature) {\n        if (!isSignature(memView)) revert UnformattedSignature();\n        return Signature.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a signature\n     */\n    function isSignature(MemView memView) internal pure returns (bool) {\n        return memView.len() == SIGNATURE_LENGTH;\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Signature signature) internal pure returns (MemView) {\n        return MemView.wrap(Signature.unwrap(signature));\n    }\n\n    // ═════════════════════════════════════════════ SIGNATURE SLICING ═════════════════════════════════════════════════\n\n    /// @notice Unpacks signature payload into (r, s, v) parameters.\n    /// @dev Make sure to verify signature length with isSignature() beforehand.\n    function toRSV(Signature signature) internal pure returns (bytes32 r, bytes32 s, uint8 v) {\n        // Get the underlying memory view\n        MemView memView = unwrap(signature);\n        r = memView.index({index_: OFFSET_R, bytes_: 32});\n        s = memView.index({index_: OFFSET_S, bytes_: 32});\n        // Can be safely casted to uint8, since we index a single byte\n        v = uint8(memView.indexUint({index_: OFFSET_V, bytes_: 1}));\n    }\n\n    // ═════════════════════════════════════════════════ CALLDATA ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the calldata with the modified arguments:\n     * the existing arguments are prepended with the arguments from the prefix.\n     * @dev Given:\n     *  - `calldata = abi.encodeWithSelector(foo.selector, d, e);`\n     *  - `prefix = abi.encode(a, b, c);`\n     *  - `a`, `b`, `c` are arguments of static type (i.e. not dynamically sized ones)\n     *      Then:\n     *  - Function will return abi.encodeWithSelector(foo.selector, a, c, c, d, e)\n     *  - Returned calldata will trigger `foo(a, b, c, d, e)` when used for a contract call.\n     * Note: for clarification as to what types are considered static, see\n     * https://docs.soliditylang.org/en/latest/abi-spec.html#formal-specification-of-the-encoding\n     * @param callData  Calldata that needs to be modified\n     * @param prefix    ABI-encoded arguments to use as the first arguments in the new calldata\n     * @return Modified calldata having prefix as the first arguments.\n     */\n    function addPrefix(CallData callData, bytes memory prefix) internal view returns (bytes memory) {\n        // Prefix should occupy a whole amount of words in memory\n        if (!_fullWords(prefix.length)) revert UnformattedCallDataPrefix();\n        MemView[] memory views = new MemView[](3);\n        // Use payload's function selector\n        views[0] = abi.encodePacked(callData.callSelector()).ref();\n        // Use prefix as the first arguments\n        views[1] = prefix.ref();\n        // Use payload's remaining arguments\n        views[2] = callData.arguments();\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a CallData view over for the given payload.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(bytes memory payload) internal pure returns (CallData) {\n        return castToCallData(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a CallData view.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(MemView memView) internal pure returns (CallData) {\n        if (!isCallData(memView)) revert UnformattedCallData();\n        return CallData.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a valid calldata, i.e.\n     * a function selector, followed by arbitrary amount of arguments.\n     */\n    function isCallData(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Calldata should at least have a function selector\n        if (length \u003c SELECTOR_LENGTH) return false;\n        // The remainder of the calldata should be exactly N memory words (N \u003e= 0)\n        return _fullWords(length - SELECTOR_LENGTH);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(CallData callData) internal pure returns (MemView) {\n        return MemView.wrap(CallData.unwrap(callData));\n    }\n\n    /// @notice Returns callData's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(CallData callData) internal pure returns (bytes32) {\n        return callData.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ CALLDATA SLICING ══════════════════════════════════════════════════\n\n    /**\n     * @notice Returns amount of memory words (32 byte chunks) the function arguments\n     * occupy in the calldata.\n     * @dev This might differ from amount of arguments supplied, if any of the arguments\n     * occupies more than one memory slot. It is true, however, that argument part of the payload\n     * occupies exactly N words, even for dynamic types like `bytes`\n     */\n    function argumentWords(CallData callData) internal pure returns (uint256) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        // Equivalent of (length - SELECTOR_LENGTH) / 32\n        return (memView.len() - SELECTOR_LENGTH) \u003e\u003e 5;\n    }\n\n    /// @notice Returns selector for the provided calldata.\n    function callSelector(CallData callData) internal pure returns (bytes4) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return bytes4(memView.index({index_: OFFSET_SELECTOR, bytes_: SELECTOR_LENGTH}));\n    }\n\n    /// @notice Returns abi encoded arguments for the provided calldata.\n    function arguments(CallData callData) internal pure returns (MemView) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return memView.sliceFrom({index_: OFFSET_ARGUMENTS});\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if length is full amount of memory words (32 bytes).\n    function _fullWords(uint256 length) internal pure returns (bool) {\n        // The equivalent of length % 32 == 0\n        return length \u0026 31 == 0;\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n    function __Context_init() internal onlyInitializing {\n    }\n\n    function __Context_init_unchained() internal onlyInitializing {\n    }\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[50] private __gap;\n}\n\n// contracts/libs/merkle/MerkleTree.sol\n\n/// `BaseTree` is a struct representing incremental merkle tree.\n/// - Contains only the current branch.\n/// - The number of inserted leaves is stored externally, and is later supplied for tree operations.\n/// - Has a fixed height of `ORIGIN_TREE_HEIGHT`.\n/// - Can store up to `2 ** ORIGIN_TREE_HEIGHT - 1` leaves.\n/// \u003e Note: the hash function for the tree `H(x, y)` is defined as:\n/// \u003e - `H(0,0) = 0`\n/// \u003e - `H(x,y) = keccak256(x, y), when (x != 0 || y != 0)`\n/// ## Invariant for leafs\n/// - The leftmost empty leaf has `index == count`, where `count` is the amount of the inserted leafs so far.\n/// - Value for any empty leaf or node is bytes32(0).\n/// ## Invariant for current branch\n/// `branch[i]` is always the value of a node on the i-th level.\n/// Levels are numbered from leafs to root: `0 .. ORIGIN_TREE_HEIGHT`.\n/// `branch[i]` stores the value for the node, such that:\n//  - The node is a \"left child\" (e.g. has an even index).\n/// - The node must have two non-empty children.\n/// - Out of all level's \"left child\" nodes with \"non-empty children\",\n/// the one with the biggest index (the rightmost one) is stored as `branch[i]`.\n/// \u003e __`branch` could be used to form a proof of inclusion for the first empty leaf (`index == count`).__\n/// _Here is how:_\n/// - Let's walk along the path from the \"first empty leaf\" to the root.\n/// - i-th bit of the \"first empty leaf\" index (which is equal to `count`) determines if the path's node\n/// for this i-th level is a \"left child\" or a \"right child\".\n/// - i-th bit in `count` is 0 → we are the left child on this level → sibling is the right child\n/// that does not exist yet → `proof[i] = bytes32(0)`.\n/// - i-th bit in `count` is 1 → we are the right child on this level → sibling is the left child\n/// sibling is the rightmost \"left child\" node on the level → `proof[i] = branch[i]`.\n/// \u003e Therefore `proof[i] = (count \u0026 (1 \u003c\u003c i)) == 0 ? bytes32(0) : branch[i])`\nstruct BaseTree {\n    bytes32[ORIGIN_TREE_HEIGHT] branch;\n}\n\nusing MerkleTree for BaseTree global;\n\n/// `HistoricalTree` is an incremental merkle tree keeping track of its historical merkle roots.\n/// \u003e - `roots[N]` is the root of the tree after `N` leafs were inserted\n/// \u003e - `roots[0] == bytes32(0)`\n/// @param tree     Incremental merkle tree\n/// @param roots    Historical merkle roots of the tree\nstruct HistoricalTree {\n    BaseTree tree;\n    bytes32[] roots;\n}\n\nusing MerkleTree for HistoricalTree global;\n\n/// `DynamicTree` is a struct representing a Merkle Tree with `2**AGENT_TREE_HEIGHT` leaves.\n/// - A single operation is available: update value for leaf with an arbitrary index (which might be a non-empty leaf).\n/// - This is done by requesting the proof of inclusion for the old value, which is used to both\n/// verify the old value, and calculate the new root.\n/// \u003e Based on Original idea from [ER forum post](https://ethresear.ch/t/efficient-on-chain-dynamic-merkle-tree/11054).\nstruct DynamicTree {\n    bytes32 root;\n}\n\nusing MerkleTree for DynamicTree global;\n\n/// MerkleTree is work based on Nomad's Merkle.sol, which is used under MIT OR Apache-2.0\n/// [link](https://github.com/nomad-xyz/monorepo/blob/main/packages/contracts-core/contracts/libs/Merkle.sol).\n/// With the following changes:\n/// - Adapted for Solidity 0.8.x.\n/// - Amount of tree leaves stored externally.\n/// - Added thorough documentation.\n/// - `H(0,0) = 0` optimization from [ER forum post](https://ethresear.ch/t/optimizing-sparse-merkle-trees/3751/6).\n/// \u003e Nomad's Merkle.sol is work based on eth2 deposit contract, which is used under CC0-1.0\n///[link](https://github.com/ethereum/deposit_contract/blob/dev/deposit_contract/contracts/validator_registration.v.py).\n/// With the following changes:\n/// \u003e - Implemented in Solidity 0.7.6 (eth2 deposit contract implemented in Vyper).\n/// \u003e - `H() = keccak256()` is used as the hashing function instead of `sha256()`.\nlibrary MerkleTree {\n    /// @dev For root calculation we need at least one empty leaf, thus the minus one in the formula.\n    uint256 internal constant MAX_LEAVES = 2 ** ORIGIN_TREE_HEIGHT - 1;\n\n    // ═════════════════════════════════════════════════ BASE TREE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Inserts `node` into merkle tree\n     * @dev Reverts if tree is full\n     * @param newCount  Amount of inserted leaves in the tree after the insertion (i.e. current + 1)\n     * @param node      Element to insert into tree\n     */\n    function insertBase(BaseTree storage tree, uint256 newCount, bytes32 node) internal {\n        if (newCount \u003e MAX_LEAVES) revert MerkleTreeFull();\n        // We go up the tree following the branch from the empty leaf AFTER the just inserted one.\n        // We stop when we find the first \"right child\" node.\n        // Its sibling is now the rightmost \"left child\" node that has two non-empty children.\n        // Therefore we need to update `tree.branch` value on this level.\n        // One could see that `tree.branch` value on lower and higher levels remain unchanged.\n\n        // Loop invariant: `node` is the current level's value for the branch from JUST INSERTED leaf\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            if ((newCount \u0026 1) == 1) {\n                // Found the first \"right child\" node on the branch from EMPTY leaf\n                // `node` is the value for node on branch from JUST INSERTED leaf\n                // Which in this case is the \"left child\".\n                // We update tree.branch and exit\n                tree.branch[i] = node;\n                return;\n            }\n            // On the branch from EMPTY leaf this is still a \"left child\".\n            // Meaning on branch from JUST INSERTED leaf, `node` is a right child.\n            // We compute value for `node` parent using `tree.branch` invariant:\n            // This is the rightmost \"left child\" node, which would be sibling of `node`.\n            node = MerkleMath.getParent(tree.branch[i], node);\n            // Get the parent index, and go to the next tree level\n            newCount \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n        // As the loop should always end prematurely with the `return` statement,\n        // this code should be unreachable. We assert `false` just to be safe.\n        assert(false);\n    }\n\n    /**\n     * @notice Calculates and returns current root of the merkle tree.\n     * @param count     Current amount of inserted leaves in the tree\n     * @return current  Calculated root of `tree`\n     */\n    function rootBase(BaseTree storage tree, uint256 count) internal view returns (bytes32 current) {\n        // To calculate the root we follow the branch of first EMPTY leaf (index == count)\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            // Check if we are the left or the right child on the current level\n            if ((count \u0026 1) == 1) {\n                // We are the right child. Our sibling is the \"rightmost\" \"left-child\" node\n                // that has two non-empty children → sibling is `tree.branch[i]`\n                current = MerkleMath.getParent(tree.branch[i], current);\n            } else {\n                // We are the left child. Our sibling does not exist yet → sibling is EMPTY\n                current = MerkleMath.getParent(current, bytes32(0));\n            }\n            // Get the parent index, and go to the next tree level\n            count \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    // ══════════════════════════════════════════════ HISTORICAL TREE ══════════════════════════════════════════════════\n\n    /// @notice Initializes the historical roots for the tree by inserting an empty root.\n    // solhint-disable-next-line ordering\n    function initializeRoots(HistoricalTree storage tree) internal returns (bytes32 savedRoot) {\n        // This should only be called once, when the contract is initialized\n        assert(tree.roots.length == 0);\n        // Save root for empty merkle tree: bytes32(0)\n        tree.roots.push(savedRoot);\n    }\n\n    /// @notice Inserts a new leaf into the merkle tree.\n    /// @dev Reverts if tree is full.\n    /// @param node         Element to insert into tree\n    /// @return newRoot     Merkle root after the leaf was inserted\n    function insert(HistoricalTree storage tree, bytes32 node) internal returns (bytes32 newRoot) {\n        // Tree count after the new leaf will be inserted (we store roots[0] as root of empty tree)\n        uint256 newCount = tree.roots.length;\n        tree.tree.insertBase(newCount, node);\n        // Save the new root\n        newRoot = tree.tree.rootBase(newCount);\n        tree.roots.push(newRoot);\n    }\n\n    /// @notice Returns the historical root of the merkle tree.\n    /// @dev Reverts if not enough leafs have been inserted.\n    /// @param count            Amount of leafs in the tree at some point of time\n    /// @return historicalRoot  Merkle root after `count` leafs were inserted\n    function root(HistoricalTree storage tree, uint256 count) internal view returns (bytes32 historicalRoot) {\n        if (count \u003e= tree.roots.length) revert NotEnoughLeafs();\n        return tree.roots[count];\n    }\n\n    // ═══════════════════════════════════════════════ DYNAMIC TREE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Updates the value for the leaf with the given index in the Dynamic Merkle Tree.\n     * @dev Will revert if incorrect proof of inclusion for old value is supplied.\n     * @param tree          Dynamic merkle tree\n     * @param index         Index of the leaf to update\n     * @param oldValue      Previous value of the leaf\n     * @param branch        Proof of inclusion of previous value into the tree\n     * @param newValue      New leaf value to assign\n     * @return newRoot      New value for the Merkle Root after the leaf is updated\n     */\n    function update(\n        DynamicTree storage tree,\n        uint256 index,\n        bytes32 oldValue,\n        bytes32[] memory branch,\n        bytes32 newValue\n    ) internal returns (bytes32 newRoot) {\n        // Check that the old value + proof result in a correct root\n        if (MerkleMath.proofRoot(index, oldValue, branch, AGENT_TREE_HEIGHT) != tree.root) {\n            revert LeafNotProven();\n        }\n        // New root is new value + the same proof (values for sibling nodes are not updated)\n        newRoot = MerkleMath.proofRoot(index, newValue, branch, AGENT_TREE_HEIGHT);\n        // Write the new root\n        tree.root = newRoot;\n    }\n}\n\n// contracts/libs/stack/Tips.sol\n\n/// Tips is encoded data with \"tips paid for sending a base message\".\n/// Note: even though uint256 is also an underlying type for MemView, Tips is stored ON STACK.\ntype Tips is uint256;\n\nusing TipsLib for Tips global;\n\n/// # Tips\n/// Library for formatting _the tips part_ of _the base messages_.\n///\n/// ## How the tips are awarded\n/// Tips are paid for sending a base message, and are split across all the agents that\n/// made the message execution on destination chain possible.\n/// ### Summit tips\n/// Split between:\n///     - Guard posting a snapshot with state ST_G for the origin chain.\n///     - Notary posting a snapshot SN_N using ST_G. This creates attestation A.\n///     - Notary posting a message receipt after it is executed on destination chain.\n/// ### Attestation tips\n/// Paid to:\n///     - Notary posting attestation A to destination chain.\n/// ### Execution tips\n/// Paid to:\n///     - First executor performing a valid execution attempt (correct proofs, optimistic period over),\n///      using attestation A to prove message inclusion on origin chain, whether the recipient reverted or not.\n/// ### Delivery tips.\n/// Paid to:\n///     - Executor who successfully executed the message on destination chain.\n///\n/// ## Tips encoding\n/// - Tips occupy a single storage word, and thus are stored on stack instead of being stored in memory.\n/// - The actual tip values should be determined by multiplying stored values by divided by TIPS_MULTIPLIER=2**32.\n/// - Tips are packed into a single word of storage, while allowing real values up to ~8*10**28 for every tip category.\n/// \u003e The only downside is that the \"real tip values\" are now multiplies of ~4*10**9, which should be fine even for\n/// the chains with the most expensive gas currency.\n/// # Tips stack layout (from highest bits to lowest)\n///\n/// | Position   | Field          | Type   | Bytes | Description                                                |\n/// | ---------- | -------------- | ------ | ----- | ---------------------------------------------------------- |\n/// | (032..024] | summitTip      | uint64 | 8     | Tip for agents interacting with Summit contract            |\n/// | (024..016] | attestationTip | uint64 | 8     | Tip for Notary posting attestation to Destination contract |\n/// | (016..008] | executionTip   | uint64 | 8     | Tip for valid execution attempt on destination chain       |\n/// | (008..000] | deliveryTip    | uint64 | 8     | Tip for successful message delivery on destination chain   |\n\nlibrary TipsLib {\n    using SafeCast for uint256;\n\n    /// @dev Amount of bits to shift to summitTip field\n    uint256 private constant SHIFT_SUMMIT_TIP = 24 * 8;\n    /// @dev Amount of bits to shift to attestationTip field\n    uint256 private constant SHIFT_ATTESTATION_TIP = 16 * 8;\n    /// @dev Amount of bits to shift to executionTip field\n    uint256 private constant SHIFT_EXECUTION_TIP = 8 * 8;\n\n    // ═══════════════════════════════════════════════════ TIPS ════════════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips with the given fields\n    /// @param summitTip_        Tip for agents interacting with Summit contract, divided by TIPS_MULTIPLIER\n    /// @param attestationTip_   Tip for Notary posting attestation to Destination contract, divided by TIPS_MULTIPLIER\n    /// @param executionTip_     Tip for valid execution attempt on destination chain, divided by TIPS_MULTIPLIER\n    /// @param deliveryTip_      Tip for successful message delivery on destination chain, divided by TIPS_MULTIPLIER\n    function encodeTips(uint64 summitTip_, uint64 attestationTip_, uint64 executionTip_, uint64 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // forgefmt: disable-next-item\n        return Tips.wrap(\n            uint256(summitTip_) \u003c\u003c SHIFT_SUMMIT_TIP |\n            uint256(attestationTip_) \u003c\u003c SHIFT_ATTESTATION_TIP |\n            uint256(executionTip_) \u003c\u003c SHIFT_EXECUTION_TIP |\n            uint256(deliveryTip_)\n        );\n    }\n\n    /// @notice Convenience function to encode tips with uint256 values.\n    function encodeTips256(uint256 summitTip_, uint256 attestationTip_, uint256 executionTip_, uint256 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // In practice, the tips amounts are not supposed to be higher than 2**96, and with 32 bits of granularity\n        // using uint64 is enough to store the values. However, we still check for overflow just in case.\n        // TODO: consider using Number type to store the tips values.\n        return encodeTips({\n            summitTip_: (summitTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            attestationTip_: (attestationTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            executionTip_: (executionTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            deliveryTip_: (deliveryTip_ \u003e\u003e TIPS_GRANULARITY).toUint64()\n        });\n    }\n\n    /// @notice Wraps the padded encoded tips into a Tips-typed value.\n    /// @dev There is no actual padding here, as the underlying type is already uint256,\n    /// but we include this function for consistency and to be future-proof, if tips will eventually use anything\n    /// smaller than uint256.\n    function wrapPadded(uint256 paddedTips) internal pure returns (Tips) {\n        return Tips.wrap(paddedTips);\n    }\n\n    /**\n     * @notice Returns a formatted Tips payload specifying empty tips.\n     * @return Formatted tips\n     */\n    function emptyTips() internal pure returns (Tips) {\n        return Tips.wrap(0);\n    }\n\n    /// @notice Returns tips's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Tips tips) internal pure returns (bytes32 hashedTips) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store tips in scratch space\n            mstore(0, tips)\n            // Compute hash of tips padded to 32 bytes\n            hashedTips := keccak256(0, 32)\n        }\n    }\n\n    // ═══════════════════════════════════════════════ TIPS SLICING ════════════════════════════════════════════════════\n\n    /// @notice Returns summitTip field\n    function summitTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_SUMMIT_TIP);\n    }\n\n    /// @notice Returns attestationTip field\n    function attestationTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_ATTESTATION_TIP);\n    }\n\n    /// @notice Returns executionTip field\n    function executionTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_EXECUTION_TIP);\n    }\n\n    /// @notice Returns deliveryTip field\n    function deliveryTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips));\n    }\n\n    // ════════════════════════════════════════════════ TIPS VALUE ═════════════════════════════════════════════════════\n\n    /// @notice Returns total value of the tips payload.\n    /// This is the sum of the encoded values, scaled up by TIPS_MULTIPLIER\n    function value(Tips tips) internal pure returns (uint256 value_) {\n        value_ = uint256(tips.summitTip()) + tips.attestationTip() + tips.executionTip() + tips.deliveryTip();\n        value_ \u003c\u003c= TIPS_GRANULARITY;\n    }\n\n    /// @notice Increases the delivery tip to match the new value.\n    function matchValue(Tips tips, uint256 newValue) internal pure returns (Tips newTips) {\n        uint256 oldValue = tips.value();\n        if (newValue \u003c oldValue) revert TipsValueTooLow();\n        // We want to increase the delivery tip, while keeping the other tips the same\n        unchecked {\n            uint256 delta = (newValue - oldValue) \u003e\u003e TIPS_GRANULARITY;\n            // `delta` fits into uint224, as TIPS_GRANULARITY is 32, so this never overflows uint256.\n            // In practice, this will never overflow uint64 as well, but we still check it just in case.\n            if (delta + tips.deliveryTip() \u003e type(uint64).max) revert TipsOverflow();\n            // Delivery tips occupy lowest 8 bytes, so we can just add delta to the tips value\n            // to effectively increase the delivery tip (knowing that delta fits into uint64).\n            newTips = Tips.wrap(Tips.unwrap(tips) + delta);\n        }\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    function __Ownable_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable_init_unchained() internal onlyInitializing {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n    function __Ownable2Step_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable2Step_init_unchained() internal onlyInitializing {\n    }\n    address private _pendingOwner;\n\n    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Returns the address of the pending owner.\n     */\n    function pendingOwner() public view virtual returns (address) {\n        return _pendingOwner;\n    }\n\n    /**\n     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual override onlyOwner {\n        _pendingOwner = newOwner;\n        emit OwnershipTransferStarted(owner(), newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual override {\n        delete _pendingOwner;\n        super._transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev The new owner accepts the ownership transfer.\n     */\n    function acceptOwnership() public virtual {\n        address sender = _msgSender();\n        require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n        _transferOwnership(sender);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// contracts/libs/memory/State.sol\n\n/// State is a memory view over a formatted state payload.\ntype State is uint256;\n\nusing StateLib for State global;\n\n/// # State\n/// State structure represents the state of Origin contract at some point of time.\n/// - State is structured in a way to track the updates of the Origin Merkle Tree.\n/// - State includes root of the Origin Merkle Tree, origin domain and some additional metadata.\n/// ## Origin Merkle Tree\n/// Hash of every sent message is inserted in the Origin Merkle Tree, which changes\n/// the value of Origin Merkle Root (which is the root for the mentioned tree).\n/// - Origin has a single Merkle Tree for all messages, regardless of their destination domain.\n/// - This leads to Origin state being updated if and only if a message was sent in a block.\n/// - Origin contract is a \"source of truth\" for states: a state is considered \"valid\" in its Origin,\n/// if it matches the state of the Origin contract after the N-th (nonce) message was sent.\n///\n/// # Memory layout of State fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                    |\n/// | ---------- | ----------- | ------- | ----- | ------------------------------ |\n/// | [000..032) | root        | bytes32 | 32    | Root of the Origin Merkle Tree |\n/// | [032..036) | origin      | uint32  | 4     | Domain where Origin is located |\n/// | [036..040) | nonce       | uint32  | 4     | Amount of sent messages        |\n/// | [040..045) | blockNumber | uint40  | 5     | Block of last sent message     |\n/// | [045..050) | timestamp   | uint40  | 5     | Time of last sent message      |\n/// | [050..062) | gasData     | uint96  | 12    | Gas data for the chain         |\n///\n/// @dev State could be used to form a Snapshot to be signed by a Guard or a Notary.\nlibrary StateLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_ROOT = 0;\n    uint256 private constant OFFSET_ORIGIN = 32;\n    uint256 private constant OFFSET_NONCE = 36;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 40;\n    uint256 private constant OFFSET_TIMESTAMP = 45;\n    uint256 private constant OFFSET_GAS_DATA = 50;\n\n    // ═══════════════════════════════════════════════════ STATE ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted State payload with provided fields\n     * @param root_         New merkle root\n     * @param origin_       Domain of Origin's chain\n     * @param nonce_        Nonce of the merkle root\n     * @param blockNumber_  Block number when root was saved in Origin\n     * @param timestamp_    Block timestamp when root was saved in Origin\n     * @param gasData_      Gas data for the chain\n     * @return Formatted state\n     */\n    function formatState(\n        bytes32 root_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_,\n        GasData gasData_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(root_, origin_, nonce_, blockNumber_, timestamp_, gasData_);\n    }\n\n    /**\n     * @notice Returns a State view over the given payload.\n     * @dev Will revert if the payload is not a state.\n     */\n    function castToState(bytes memory payload) internal pure returns (State) {\n        return castToState(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a State view.\n     * @dev Will revert if the memory view is not over a state.\n     */\n    function castToState(MemView memView) internal pure returns (State) {\n        if (!isState(memView)) revert UnformattedState();\n        return State.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted State.\n    function isState(MemView memView) internal pure returns (bool) {\n        return memView.len() == STATE_LENGTH;\n    }\n\n    /// @notice Returns the hash of a State, that could be later signed by a Guard to signal\n    /// that the state is invalid.\n    function hashInvalid(State state) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(stateInvalidSalt, keccak(state))\n        return state.unwrap().keccakSalted(STATE_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(State state) internal pure returns (MemView) {\n        return MemView.wrap(State.unwrap(state));\n    }\n\n    /// @notice Compares two State structures.\n    function equals(State a, State b) internal pure returns (bool) {\n        // Length of a State payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═══════════════════════════════════════════════ STATE HASHING ═══════════════════════════════════════════════════\n\n    /// @notice Returns the hash of the State.\n    /// @dev We are using the Merkle Root of a tree with two leafs (see below) as state hash.\n    function leaf(State state) internal pure returns (bytes32) {\n        (bytes32 leftLeaf_, bytes32 rightLeaf_) = state.subLeafs();\n        // Final hash is the parent of these leafs\n        return keccak256(bytes.concat(leftLeaf_, rightLeaf_));\n    }\n\n    /// @notice Returns \"sub-leafs\" of the State. Hash of these \"sub leafs\" is going to be used\n    /// as a \"state leaf\" in the \"Snapshot Merkle Tree\".\n    /// This enables proving that leftLeaf = (root, origin) was a part of the \"Snapshot Merkle Tree\",\n    /// by combining `rightLeaf` with the remainder of the \"Snapshot Merkle Proof\".\n    function subLeafs(State state) internal pure returns (bytes32 leftLeaf_, bytes32 rightLeaf_) {\n        MemView memView = state.unwrap();\n        // Left leaf is (root, origin)\n        leftLeaf_ = memView.prefix({len_: OFFSET_NONCE}).keccak();\n        // Right leaf is (metadata), or (nonce, blockNumber, timestamp)\n        rightLeaf_ = memView.sliceFrom({index_: OFFSET_NONCE}).keccak();\n    }\n\n    /// @notice Returns the left \"sub-leaf\" of the State.\n    function leftLeaf(bytes32 root_, uint32 origin_) internal pure returns (bytes32) {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(root_, origin_));\n    }\n\n    /// @notice Returns the right \"sub-leaf\" of the State.\n    function rightLeaf(uint32 nonce_, uint40 blockNumber_, uint40 timestamp_, GasData gasData_)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(nonce_, blockNumber_, timestamp_, gasData_));\n    }\n\n    // ═══════════════════════════════════════════════ STATE SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns a historical Merkle root from the Origin contract.\n    function root(State state) internal pure returns (bytes32) {\n        return state.unwrap().index({index_: OFFSET_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns domain of chain where the Origin contract is deployed.\n    function origin(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns nonce of Origin contract at the time, when `root` was the Merkle root.\n    function nonce(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when `root` was saved in Origin.\n    function blockNumber(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when `root` was saved in Origin.\n    /// @dev This is the timestamp according to the origin chain.\n    function timestamp(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n\n    /// @notice Returns gas data for the chain.\n    function gasData(State state) internal pure returns (GasData) {\n        return GasDataLib.wrapGasData(state.unwrap().indexUint({index_: OFFSET_GAS_DATA, bytes_: GAS_DATA_LENGTH}));\n    }\n}\n\n// contracts/libs/memory/BaseMessage.sol\n\n/// BaseMessage is a memory view over the base message supported by Origin-Destination\ntype BaseMessage is uint256;\n\nusing BaseMessageLib for BaseMessage global;\n\n/// BaseMessage structure represents a base message sent via the Origin-Destination contracts.\n/// - It only contains data relevant to the base message, the rest of data is encoded in the message header.\n/// - `sender` and `recipient` for EVM chains are EVM addresses casted to bytes32, while preserving left-alignment.\n/// - `tips` and `request` parameters are specified by a message sender\n/// \u003e Origin will calculate minimum tips for given request and content length, and will reject messages with tips\n/// lower than that.\n///\n/// # Memory layout of BaseMessage fields\n///\n/// | Position   | Field     | Type    | Bytes | Description                            |\n/// | ---------- | --------- | ------- | ----- | -------------------------------------- |\n/// | [000..032) | tips      | uint256 | 32    | Encoded tips paid on origin chain      |\n/// | [032..064) | sender    | bytes32 | 32    | Sender address on origin chain         |\n/// | [064..096) | recipient | bytes32 | 32    | Recipient address on destination chain |\n/// | [096..116) | request   | uint160 | 20    | Encoded request for message execution  |\n/// | [104..AAA) | content   | bytes   | ??    | Content to be passed to recipient      |\nlibrary BaseMessageLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_TIPS = 0;\n    uint256 private constant OFFSET_SENDER = 32;\n    uint256 private constant OFFSET_RECIPIENT = 64;\n    uint256 private constant OFFSET_REQUEST = OFFSET_RECIPIENT + TIPS_LENGTH;\n    uint256 private constant OFFSET_CONTENT = OFFSET_REQUEST + REQUEST_LENGTH;\n\n    // ═══════════════════════════════════════════════ BASE MESSAGE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted BaseMessage payload with provided fields.\n     * @param tips_         Encoded tips information\n     * @param sender_       Sender address on origin chain\n     * @param recipient_    Recipient address on destination chain\n     * @param request_      Encoded request for message execution\n     * @param content_      Raw content to be passed to recipient on destination chain\n     * @return Formatted base message\n     */\n    function formatBaseMessage(Tips tips_, bytes32 sender_, bytes32 recipient_, Request request_, bytes memory content_)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return abi.encodePacked(tips_, sender_, recipient_, request_, content_);\n    }\n\n    /**\n     * @notice Returns a BaseMessage view over the given payload.\n     * @dev Will revert if the payload is not a base message.\n     */\n    function castToBaseMessage(bytes memory payload) internal pure returns (BaseMessage) {\n        return castToBaseMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a BaseMessage view.\n     * @dev Will revert if the memory view is not over a base message payload.\n     */\n    function castToBaseMessage(MemView memView) internal pure returns (BaseMessage) {\n        if (!isBaseMessage(memView)) revert UnformattedBaseMessage();\n        return BaseMessage.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted BaseMessage.\n    function isBaseMessage(MemView memView) internal pure returns (bool) {\n        // Check if sender, recipient, tips fields exist\n        return (memView.len() \u003e= OFFSET_CONTENT);\n        // Content could be empty, so we don't check that\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(BaseMessage baseMessage) internal pure returns (MemView) {\n        return MemView.wrap(BaseMessage.unwrap(baseMessage));\n    }\n\n    /// @notice Returns baseMessage's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        // We hash \"tips\" and \"everything but tips\" to make tips proofs easier to verify\n        return MerkleMath.getParent(baseMessage.tips().leaf(), baseMessage.bodyLeaf());\n    }\n\n    /// @notice Returns hash for the \"everything but tips\" part of the base message.\n    function bodyLeaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_SENDER}).keccak();\n    }\n\n    // ═══════════════════════════════════════════ BASE MESSAGE SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips paid on origin chain.\n    function tips(BaseMessage baseMessage) internal pure returns (Tips) {\n        return TipsLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_TIPS, bytes_: TIPS_LENGTH})));\n    }\n\n    /// @notice Returns sender address on origin chain.\n    function sender(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_SENDER, bytes_: 32});\n    }\n\n    /// @notice Returns recipient address on destination chain.\n    function recipient(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_RECIPIENT, bytes_: 32});\n    }\n\n    /// @notice Returns an encoded request for message execution on destination chain.\n    function request(BaseMessage baseMessage) internal pure returns (Request) {\n        return RequestLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_REQUEST, bytes_: REQUEST_LENGTH})));\n    }\n\n    /// @notice Returns an untyped memory view over the content to be passed to recipient.\n    function content(BaseMessage baseMessage) internal pure returns (MemView) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_CONTENT});\n    }\n}\n\n// contracts/base/MessagingBase.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for all messaging contracts.\n * - Provides context on the local chain's domain.\n * - Provides ownership functionality.\n * - Will be providing pausing functionality when it is implemented.\n */\nabstract contract MessagingBase is MultiCallable, Versioned, Ownable2StepUpgradeable {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @notice Domain of the local chain, set once upon contract creation\n    uint32 public immutable localDomain;\n    // @notice Domain of the Synapse chain, set once upon contract creation\n    uint32 public immutable synapseDomain;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev gap for upgrade safety\n    uint256[50] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    constructor(string memory version_, uint32 synapseDomain_) Versioned(version_) {\n        localDomain = ChainContext.chainId();\n        synapseDomain = synapseDomain_;\n    }\n\n    // TODO: Implement pausing\n\n    /**\n     * @dev Should be impossible to renounce ownership;\n     * we override OpenZeppelin OwnableUpgradeable's\n     * implementation of renounceOwnership to make it a no-op\n     */\n    function renounceOwnership() public override onlyOwner {} //solhint-disable-line no-empty-blocks\n}\n\n// contracts/libs/memory/Message.sol\n\n/// Message is a memory over over a formatted message payload.\ntype Message is uint256;\n\nusing MessageLib for Message global;\n\n/// Library for formatting the various messages supported by Origin and Destination.\n///\n/// # Message memory layout\n///\n/// | Position   | Field  | Type    | Bytes | Description                                             |\n/// | ---------- | ------ | ------- | ----- | ------------------------------------------------------- |\n/// | [000..017) | header | uint136 | 17    | Encoded general routing information for the message     |\n/// | [017..AAA) | body   | bytes   | ??    | Formatted payload (according to flag) with message body |\nlibrary MessageLib {\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MemViewLib for bytes;\n    using HeaderLib for MemView;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_HEADER = 0;\n    uint256 private constant OFFSET_BODY = OFFSET_HEADER + HEADER_LENGTH;\n\n    // ══════════════════════════════════════════════════ MESSAGE ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns formatted message with provided fields.\n     * @param header_   Encoded general routing information for the message\n     * @param body_     Formatted payload (according to flag) with message body\n     * @return Formatted message\n     */\n    function formatMessage(Header header_, bytes memory body_) internal pure returns (bytes memory) {\n        return abi.encodePacked(header_, body_);\n    }\n\n    /**\n     * @notice Returns a Message view over for the given payload.\n     * @dev Will revert if the payload is not a message payload.\n     */\n    function castToMessage(bytes memory payload) internal pure returns (Message) {\n        return castToMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Message view.\n     * @dev Will revert if the memory view is not over a message payload.\n     */\n    function castToMessage(MemView memView) internal pure returns (Message) {\n        if (!isMessage(memView)) revert UnformattedMessage();\n        return Message.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Message.\n     */\n    function isMessage(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Check if headers exist in the payload\n        if (length \u003c OFFSET_BODY) return false;\n        // Check that Header is valid\n        uint256 paddedHeader = _header(memView);\n        if (!HeaderLib.isHeader(paddedHeader)) return false;\n        // Check that body is formatted according to the flag\n        // Only Base/Manager message flags exist\n        if (HeaderLib.wrapPadded(paddedHeader).flag() == MessageFlag.Base) {\n            // Check if body is a formatted base message\n            return _body(memView).isBaseMessage();\n        } else {\n            // Check if body is a formatted calldata for AgentManager call\n            return _body(memView).isCallData();\n        }\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Message message) internal pure returns (MemView) {\n        return MemView.wrap(Message.unwrap(message));\n    }\n\n    /// @notice Returns message's hash: a leaf to be inserted in the Merkle tree.\n    function leaf(Message message) internal pure returns (bytes32) {\n        // We hash header and body separately to make message proofs easier to verify\n        Header header_ = message.header();\n        // Only Base/Manager message flags exist\n        if (header_.flag() == MessageFlag.Base) {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToBaseMessage().leaf());\n        } else {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToCallData().leaf());\n        }\n    }\n\n    // ══════════════════════════════════════════════ MESSAGE SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns message's encoded header field.\n    function header(Message message) internal pure returns (Header) {\n        return HeaderLib.wrapPadded((message.unwrap().indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH})));\n    }\n\n    /// @notice Returns message's body field as an untyped memory view.\n    function body(Message message) internal pure returns (MemView) {\n        MemView memView = message.unwrap();\n        return _body(memView);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns message's padded header without checking that it is a valid header.\n    function _header(MemView memView) private pure returns (uint256) {\n        return memView.indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH});\n    }\n\n    /// @dev Returns an untyped memory view over the body field without checking\n    /// if the whole payload or the body are properly formatted.\n    function _body(MemView memView) private pure returns (MemView) {\n        return memView.sliceFrom({index_: OFFSET_BODY});\n    }\n}\n\n// contracts/base/AgentSecured.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for messaging contracts that are secured by the agent manager.\n * `AgentSecured` relies on `AgentManager` to provide the following functionality:\n * - Keep track of agents and their statuses.\n * - Pass agent-signed statements that were verified by the agent manager.\n * - These statements are considered valid indefinitely, unless the agent is disputed.\n * - Disputes are opened and resolved by the agent manager.\n * \u003e `AgentSecured` implementation should never use statements signed by agents that are disputed.\n */\nabstract contract AgentSecured is MessagingBase, IAgentSecured {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    address public immutable agentManager;\n\n    /// @inheritdoc IAgentSecured\n    address public immutable inbox;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    // (agent index =\u003e their dispute status: flag, openedAt, resolvedAt)\n    mapping(uint32 =\u003e DisputeStatus) internal _disputes;\n\n    /// @dev gap for upgrade safety\n    uint256[49] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    modifier onlyAgentManager() {\n        if (msg.sender != agentManager) revert CallerNotAgentManager();\n        _;\n    }\n\n    modifier onlyInbox() {\n        if (msg.sender != inbox) revert CallerNotInbox();\n        _;\n    }\n\n    constructor(string memory version_, uint32 synapseDomain_, address agentManager_, address inbox_)\n        MessagingBase(version_, synapseDomain_)\n    {\n        agentManager = agentManager_;\n        inbox = inbox_;\n    }\n\n    // ════════════════════════════════════════════ ONLY AGENT MANAGER ═════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external onlyAgentManager {\n        uint40 openedAt = ChainContext.blockTimestamp();\n        DisputeStatus memory status = DisputeStatus({flag: DisputeFlag.Pending, openedAt: openedAt, resolvedAt: 0});\n        _disputes[guardIndex] = status;\n        _disputes[notaryIndex] = status;\n    }\n\n    /// @inheritdoc IAgentSecured\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external onlyAgentManager {\n        // Update the dispute status of the slashed agent first.\n        uint40 resolvedAt = ChainContext.blockTimestamp();\n        _disputes[slashedIndex].flag = DisputeFlag.Slashed;\n        _disputes[slashedIndex].resolvedAt = resolvedAt;\n        // Mark the rival agent as not disputed, if there was an ongoing dispute.\n        if (rivalIndex != 0) {\n            _disputes[rivalIndex].flag = DisputeFlag.None;\n            _disputes[rivalIndex].resolvedAt = resolvedAt;\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function agentStatus(address agent) external view returns (AgentStatus memory) {\n        return _agentStatus(agent);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status) {\n        return _getAgent(index);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory) {\n        return _disputes[agentIndex];\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns status of the given agent: (flag, domain, index).\n    function _agentStatus(address agent) internal view returns (AgentStatus memory) {\n        return IAgentManager(agentManager).agentStatus(agent);\n    }\n\n    /// @dev Returns agent and their status for a given agent index. Returns zero values for non existing indexes.\n    function _getAgent(uint256 index) internal view returns (address agent, AgentStatus memory status) {\n        return IAgentManager(agentManager).getAgent(index);\n    }\n\n    /// @dev Checks if a Dispute exists for the given Notary. This function returns true, if\n    /// Notary is in ongoing Dispute, or if Dispute was resolved not in Notary's favor.\n    /// In both cases we can't trust Notary's data.\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeExists(uint32 notaryIndex) internal view returns (bool) {\n        return _disputes[notaryIndex].flag != DisputeFlag.None;\n    }\n\n    /// @dev Checks if a Notary recently won a Dispute and is still in the \"post-dispute\" timeout period.\n    /// In this period we still can't trust Notary's data, though we can optimistically assume that\n    /// that the data will be correct after the timeout (assuming no new Disputes are opened).\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeTimeout(uint32 notaryIndex) internal view returns (bool) {\n        DisputeStatus memory status = _disputes[notaryIndex];\n        // Exit early if Notary is in ongoing Dispute / slashed.\n        if (status.flag != DisputeFlag.None) return false;\n        // Check if Notary has been in any Dispute at all.\n        if (status.openedAt == 0) return false;\n        // Otherwise check if the Dispute timeout is still active.\n        return block.timestamp \u003c status.resolvedAt + DISPUTE_TIMEOUT_NOTARY;\n    }\n}\n\n// contracts/hubs/StateHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StateHub` is a parent contract for `Origin`. It is responsible for the following:\n/// - Keeping track of the historical Origin Merkle Tree containing all the message hashes.\n/// - Keeping track of the historical Origin States, as well as verifying their validity.\nabstract contract StateHub is AgentSecured, StateHubEvents, IStateHub {\n    using SafeCast for uint256;\n    using StateLib for bytes;\n\n    struct OriginState {\n        uint40 blockNumber;\n        uint40 timestamp;\n        GasData gasData;\n    }\n    // Bits left for tight packing: 80\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Historical Merkle Tree\n    /// Note: Takes two storage slots\n    HistoricalTree private _tree;\n\n    /// @dev All historical contract States\n    OriginState[] private _originStates;\n\n    /// @dev gap for upgrade safety\n    uint256[47] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IStateHub\n    function isValidState(bytes memory statePayload) external view returns (bool isValid) {\n        // This will revert if payload is not a formatted state\n        State state = statePayload.castToState();\n        return _isValidState(state);\n    }\n\n    /// @inheritdoc IStateHub\n    function statesAmount() external view returns (uint256) {\n        return _originStates.length;\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestLatestState() external view returns (bytes memory stateData) {\n        // This never underflows, assuming the contract was initialized\n        return suggestState(_nextNonce() - 1);\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestState(uint32 nonce) public view returns (bytes memory stateData) {\n        // This will revert if nonce is out of range\n        bytes32 root = _tree.root(nonce);\n        return _formatOriginState(_originStates[nonce], root, localDomain, nonce);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Initializes the saved states list by inserting a state for an empty Merkle Tree.\n    function _initializeStates() internal {\n        // This should only be called once, when the contract is initialized\n        // This will revert if _tree.roots is non-empty\n        bytes32 savedRoot = _tree.initializeRoots();\n        // Save root for empty merkle _tree with block number and timestamp of initialization\n        _saveState(savedRoot, _toOriginState());\n    }\n\n    /// @dev Inserts leaf into the Merkle Tree and saves the updated origin State.\n    function _insertAndSave(bytes32 leaf) internal {\n        bytes32 newRoot = _tree.insert(leaf);\n        _saveState(newRoot, _toOriginState());\n    }\n\n    /// @dev Saves an updated state of the Origin contract\n    function _saveState(bytes32 root, OriginState memory state) internal {\n        uint32 nonce = _nextNonce();\n        _originStates.push(state);\n        // Emit event with raw state data\n        emit StateSaved(_formatOriginState(state, root, localDomain, nonce));\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns nonce of the next sent message: the amount of saved States so far.\n    /// This always equals to \"total amount of sent messages\" plus 1.\n    function _nextNonce() internal view returns (uint32) {\n        // TODO: consider using more than 32 bits for origin nonces\n        return _originStates.length.toUint32();\n    }\n\n    /// @dev Checks if a state is valid, i.e. if it matches the historical one.\n    /// Reverts, if state refers to another Origin contract.\n    function _isValidState(State state) internal view returns (bool) {\n        // Check if state refers to this contract\n        if (state.origin() != localDomain) revert IncorrectOriginDomain();\n        // Check if nonce exists\n        uint32 nonce = state.nonce();\n        if (nonce \u003e= _originStates.length) return false;\n        // Check if state root matches the historical one\n        if (state.root() != _tree.root(nonce)) return false;\n        // Check if state metadata matches the historical one\n        return _areEqual(state, _originStates[nonce]);\n    }\n\n    // ═════════════════════════════════════════════ STRUCT FORMATTING ═════════════════════════════════════════════════\n\n    /// @dev Returns a formatted payload for a stored OriginState.\n    function _formatOriginState(OriginState memory originState, bytes32 root, uint32 origin, uint32 nonce)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return StateLib.formatState({\n            root_: root,\n            origin_: origin,\n            nonce_: nonce,\n            blockNumber_: originState.blockNumber,\n            timestamp_: originState.timestamp,\n            gasData_: originState.gasData\n        });\n    }\n\n    /// @dev Child contract should implement the logic for getting the current gas data from the gas oracle\n    /// to be saved as part of the Origin State.\n    // solhint-disable-next-line ordering\n    function _fetchGasData() internal view virtual returns (GasData);\n\n    /// @dev Returns a OriginState struct to save in the contract.\n    function _toOriginState() internal view returns (OriginState memory originState) {\n        originState.blockNumber = ChainContext.blockNumber();\n        originState.timestamp = ChainContext.blockTimestamp();\n        originState.gasData = _fetchGasData();\n    }\n\n    /// @dev Checks that a state and its Origin representation are equal.\n    function _areEqual(State state, OriginState memory originState) internal pure returns (bool) {\n        return state.blockNumber() == originState.blockNumber \u0026\u0026 state.timestamp() == originState.timestamp;\n    }\n}\n\n// contracts/Origin.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Origin` contract is used for sending messages to remote chains. It is done\n/// by inserting the message hashes into the Origin Merkle, which makes it possible to\n/// prove that message was sent using the Merkle proof against the Origin Merkle Root. This essentially\n/// compresses the list of messages into a single 32-byte value that needs to be stored on the destination chain.\n/// `Origin` is responsible for the following:\n/// - Formatting the sent message payloads, and inserting their hashes into the Origin Merkle Tree.\n/// - Keeping track of its own historical states (see parent contract `StateHub`).\n/// - Enforcing minimum tip values for sent base messages based on the provided execution requests.\n/// - Distributing the collected tips upon request from a local `AgentManager` contract.\ncontract Origin is StateHub, OriginEvents, InterfaceOrigin {\n    using MemViewLib for bytes;\n    using MessageLib for bytes;\n    using TipsLib for bytes;\n    using TypeCasts for address;\n\n    address public immutable gasOracle;\n\n    modifier onlyRemoteDestination(uint32 destination) {\n        if (destination == localDomain) revert IncorrectDestinationDomain();\n        _;\n    }\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_, address gasOracle_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {\n        gasOracle = gasOracle_;\n    }\n\n    /// @notice Initializes Origin contract:\n    /// - msg.sender is set as contract owner\n    /// - State of \"empty merkle tree\" is saved\n    function initialize() external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize \"states\": state of an \"empty merkle tree\" is saved\n        _initializeStates();\n    }\n\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable onlyRemoteDestination(destination) returns (uint32 messageNonce, bytes32 messageHash) {\n        // Check that content is not too large\n        if (content.length \u003e MAX_CONTENT_BYTES) revert ContentLengthTooBig();\n        // This will revert if msg.value is lower than value of minimum tips\n        Tips tips = _getMinimumTips(destination, paddedRequest, content.length).matchValue(msg.value);\n        Request request = RequestLib.wrapPadded(paddedRequest);\n        // Format the BaseMessage body\n        bytes memory body = BaseMessageLib.formatBaseMessage({\n            sender_: msg.sender.addressToBytes32(),\n            recipient_: recipient,\n            tips_: tips,\n            request_: request,\n            content_: content\n        });\n        // Send the message\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Base, body);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        onlyAgentManager\n        onlyRemoteDestination(destination)\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // AgentManager (checked via modifier) is responsible for constructing the calldata payload correctly.\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Manager, payload);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function withdrawTips(address recipient, uint256 amount) external onlyAgentManager {\n        if (address(this).balance \u003c amount) revert InsufficientEthBalance();\n        (bool success,) = recipient.call{value: amount}(\"\");\n        if (!success) revert EthTransferFailed();\n        emit TipWithdrawalCompleted(recipient, amount);\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue)\n    {\n        return _getMinimumTips(destination, paddedRequest, contentLength).value();\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Sends the given message to the specified destination. Message hash is inserted\n    /// into the Origin Merkle Tree, which will enable message execution on destination chain.\n    function _sendMessage(uint32 destination, uint32 optimisticPeriod, MessageFlag flag, bytes memory body)\n        internal\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // Format the message header\n        messageNonce = _nextNonce();\n        Header header = flag.encodeHeader({\n            origin_: localDomain,\n            nonce_: messageNonce,\n            destination_: destination,\n            optimisticPeriod_: optimisticPeriod\n        });\n        // Format the full message payload\n        bytes memory msgPayload = MessageLib.formatMessage(header, body);\n        // Insert new leaf into the Origin Merkle Tree and save the updated state\n        messageHash = msgPayload.castToMessage().leaf();\n        _insertAndSave(messageHash);\n        // Emit event with message information\n        emit Sent(messageHash, messageNonce, destination, msgPayload);\n        // Update the gas oracle data. We do this after the provided tips are checked so that\n        // the provided message is sent in the event that the gas oracle data is updated to a higher value.\n        InterfaceGasOracle(gasOracle).updateGasData(destination);\n        // TODO: consider doing this before the message is sent, while adjusting GasOracle.getMinimumTips() to\n        // use the pending gas oracle data.\n    }\n\n    /// @dev Returns the minimum tips for sending a message to the given destination with the given request and content.\n    function _getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        internal\n        view\n        returns (Tips)\n    {\n        return\n            TipsLib.wrapPadded(InterfaceGasOracle(gasOracle).getMinimumTips(destination, paddedRequest, contentLength));\n    }\n\n    /// @dev Gets the current gas data from the gas oracle to be saved as part of the Origin State.\n    function _fetchGasData() internal view override returns (GasData) {\n        return GasDataLib.wrapGasData(InterfaceGasOracle(gasOracle).getGasData());\n    }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"","srcMapRuntime":"","abiDefinition":[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"state","type":"bytes"}],"name":"StateSaved","type":"event"}],"userDoc":{"events":{"StateSaved(bytes)":{"notice":"Emitted when a new Origin State is saved after a message was sent."}},"kind":"user","methods":{},"notice":"A collection of events emitted by the StateHub contract","version":1},"developerDoc":{"events":{"StateSaved(bytes)":{"params":{"state":"Raw payload with state data"}}},"kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"state\",\"type\":\"bytes\"}],\"name\":\"StateSaved\",\"type\":\"event\"}],\"devdoc\":{\"events\":{\"StateSaved(bytes)\":{\"params\":{\"state\":\"Raw payload with state data\"}}},\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"events\":{\"StateSaved(bytes)\":{\"notice\":\"Emitted when a new Origin State is saved after a message was sent.\"}},\"kind\":\"user\",\"methods\":{},\"notice\":\"A collection of events emitted by the StateHub contract\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Origin.sol\":\"StateHubEvents\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Origin.sol\":{\"keccak256\":\"0x96775924f147f3d1f8df8cdf56731fe52a15af8d8e12e608efb8158c112b18cd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e642a27f5fab3c62b4c02e9754e9e42b1cf2e5381dbea9d3d106d23b7772ebe6\",\"dweb:/ipfs/QmUwn7ZyBvPkjnMuK8ZMSexBUdNQnVtxwyoAyT4DXLQjra\"]}},\"version\":1}"},"hashes":{}},"solidity/Origin.sol:StateLib":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220b1dc4e073bfc0b58d5e6ef98007a541b15f82cd5f480490a26ef12061a35dd4664736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220b1dc4e073bfc0b58d5e6ef98007a541b15f82cd5f480490a26ef12061a35dd4664736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/OriginEvents.sol\n\n/// @notice A collection of events emitted by the Origin contract\nabstract contract OriginEvents {\n    /**\n     * @notice Emitted when a new message is sent.\n     * @param messageHash   Hash of message; the leaf inserted to the Merkle tree for the message\n     * @param nonce         Nonce of sent message (starts from 1)\n     * @param destination   Destination domain\n     * @param message       Raw bytes of message\n     */\n    event Sent(bytes32 indexed messageHash, uint32 indexed nonce, uint32 indexed destination, bytes message);\n\n    /**\n     * @notice Emitted when a tip withdrawal is completed.\n     * @param actor     Actor address\n     * @param tip       Tip value, denominated in local domain's wei\n     */\n    event TipWithdrawalCompleted(address actor, uint256 tip);\n}\n\n// contracts/events/StateHubEvents.sol\n\n/// @notice A collection of events emitted by the StateHub contract\nabstract contract StateHubEvents {\n    /**\n     * @notice Emitted when a new Origin State is saved after a message was sent.\n     * @param state     Raw payload with state data\n     */\n    event StateSaved(bytes state);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n    /**\n     * @notice Check that a given state is valid: matches the historical state of Origin contract.\n     * Note: any Agent including an invalid state in their snapshot will be slashed\n     * upon providing the snapshot and agent signature for it to Origin contract.\n     * @dev Will revert if any of these is true:\n     *  - State payload is not properly formatted.\n     * @param statePayload      Raw payload with state data\n     * @return isValid          Whether the provided state is valid\n     */\n    function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns the amount of saved states so far.\n     * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n     */\n    function statesAmount() external view returns (uint256);\n\n    /**\n     * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @return statePayload     Raw payload with the latest state data\n     */\n    function suggestLatestState() external view returns (bytes memory statePayload);\n\n    /**\n     * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @param nonce             Historical nonce to form a state\n     * @return statePayload     Raw payload with historical state data\n     */\n    function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/InterfaceGasOracle.sol\n\ninterface InterfaceGasOracle {\n    /**\n     * @notice Fetches the latest gas data for the chain from `Destination` contract,\n     * and uses it to update the oracle values for the requested chain.\n     * @param domain    Domain to update the gas data for\n     */\n    function updateGasData(uint32 domain) external;\n\n    /**\n     * @notice Returns the gas data for the local chain.\n     */\n    function getGasData() external view returns (uint256 paddedGasData);\n\n    /**\n     * @notice Returns the gas data for the given domain, in the decoded format.\n     * @param domain        Domain of chain to get gas data for\n     * @return gasPrice     Gas price for the chain (in Wei per gas unit)\n     * @return dataPrice    Calldata price (in Wei per byte of content)\n     * @return execBuffer   Tx fee safety buffer for message execution (in Wei)\n     * @return amortAttCost Amortized cost for attestation submission (in Wei)\n     * @return etherPrice   Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n     * @return markup       Markup for the message execution (in BWAD)\n     */\n    function getDecodedGasData(uint32 domain)\n        external\n        view\n        returns (\n            uint256 gasPrice,\n            uint256 dataPrice,\n            uint256 execBuffer,\n            uint256 amortAttCost,\n            uint256 etherPrice,\n            uint256 markup\n        );\n\n    /**\n     * @notice Returns the minimum tips for sending a message to a given destination.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return paddedTips       Padded encoded minimum tips information\n     */\n    function getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 paddedTips);\n}\n\n// contracts/interfaces/InterfaceOrigin.sol\n\ninterface InterfaceOrigin {\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /**\n     * @notice Send a message to the recipient located on destination domain.\n     * @dev Recipient has to conform to IMessageRecipient interface, otherwise message won't be delivered.\n     * Will revert if any of these is true:\n     * - `destination` is equal to contract's local domain\n     * - `content` length is greater than `MAX_CONTENT_BYTES`\n     * - `msg.value` is lower than value of minimum tips for the given message\n     * @param destination           Domain of destination chain\n     * @param recipient             Address of recipient on destination chain as bytes32\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param paddedRequest         Padded encoded message execution request on destination chain\n     * @param content               Raw bytes content of message\n     * @return messageNonce         Nonce of the sent message\n     * @return messageHash          Hash of the sent message\n     */\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable returns (uint32 messageNonce, bytes32 messageHash);\n\n    /**\n     * @notice Send a manager message to the destination domain.\n     * @dev This could only be called by AgentManager, which takes care of encoding the calldata payload.\n     * Note: (msgOrigin, proofMaturity) security args will be added to payload on the destination chain\n     * so that the AgentManager could verify where the Manager Message came from and how mature is the proof.\n     * Note: function is not payable, as no tips are required for sending a manager message.\n     * Will revert if `destination` is equal to contract's local domain.\n     * @param destination           Domain of destination chain\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param payload               Payload for calling AgentManager on destination chain (with extra security args)\n     */\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        returns (uint32 messageNonce, bytes32 messageHash);\n\n    // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Withdraws locked base message tips to the recipient.\n     * @dev Could only be called by a local AgentManager.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function withdrawTips(address recipient, uint256 amount) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the minimum tips value for sending a message to a given destination.\n     * @dev Using at least `tipsValue` as `msg.value` for `sendBaseMessage()`\n     * will guarantee that the message will be accepted.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return tipsValue        Minimum tips value for a message to be accepted\n     */\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue);\n}\n\n// contracts/libs/Constants.sol\n\n// Here we define common constants to enable their easier reusing later.\n\n// ══════════════════════════════════ MERKLE ═══════════════════════════════════\n/// @dev Height of the Agent Merkle Tree\nuint256 constant AGENT_TREE_HEIGHT = 32;\n/// @dev Height of the Origin Merkle Tree\nuint256 constant ORIGIN_TREE_HEIGHT = 32;\n/// @dev Height of the Snapshot Merkle Tree. Allows up to 64 leafs, e.g. up to 32 states\nuint256 constant SNAPSHOT_TREE_HEIGHT = 6;\n// ══════════════════════════════════ STRUCTS ══════════════════════════════════\n/// @dev See Attestation.sol: (bytes32,bytes32,uint32,uint40,uint40): 32+32+4+5+5\nuint256 constant ATTESTATION_LENGTH = 78;\n/// @dev See GasData.sol: (uint16,uint16,uint16,uint16,uint16,uint16): 2+2+2+2+2+2\nuint256 constant GAS_DATA_LENGTH = 12;\n/// @dev See Receipt.sol: (uint32,uint32,bytes32,bytes32,uint8,address,address,address): 4+4+32+32+1+20+20+20\nuint256 constant RECEIPT_LENGTH = 133;\n/// @dev See State.sol: (bytes32,uint32,uint32,uint40,uint40,GasData): 32+4+4+5+5+len(GasData)\nuint256 constant STATE_LENGTH = 50 + GAS_DATA_LENGTH;\n/// @dev Maximum amount of states in a single snapshot. Each state produces two leafs in the tree\nuint256 constant SNAPSHOT_MAX_STATES = 1 \u003c\u003c (SNAPSHOT_TREE_HEIGHT - 1);\n// ══════════════════════════════════ MESSAGE ══════════════════════════════════\n/// @dev See Header.sol: (uint8,uint32,uint32,uint32,uint32): 1+4+4+4+4\nuint256 constant HEADER_LENGTH = 17;\n/// @dev See Request.sol: (uint96,uint64,uint32): 12+8+4\nuint256 constant REQUEST_LENGTH = 24;\n/// @dev See Tips.sol: (uint64,uint64,uint64,uint64): 8+8+8+8\nuint256 constant TIPS_LENGTH = 32;\n/// @dev The amount of discarded last bits when encoding tip values\nuint256 constant TIPS_GRANULARITY = 32;\n/// @dev Tip values could be only the multiples of TIPS_MULTIPLIER\nuint256 constant TIPS_MULTIPLIER = 1 \u003c\u003c TIPS_GRANULARITY;\n// ══════════════════════════════ STATEMENT SALTS ══════════════════════════════\n/// @dev Salts for signing various statements\nbytes32 constant ATTESTATION_VALID_SALT = keccak256(\"ATTESTATION_VALID_SALT\");\nbytes32 constant ATTESTATION_INVALID_SALT = keccak256(\"ATTESTATION_INVALID_SALT\");\nbytes32 constant RECEIPT_VALID_SALT = keccak256(\"RECEIPT_VALID_SALT\");\nbytes32 constant RECEIPT_INVALID_SALT = keccak256(\"RECEIPT_INVALID_SALT\");\nbytes32 constant SNAPSHOT_VALID_SALT = keccak256(\"SNAPSHOT_VALID_SALT\");\nbytes32 constant STATE_INVALID_SALT = keccak256(\"STATE_INVALID_SALT\");\n// ═════════════════════════════════ PROTOCOL ══════════════════════════════════\n/// @dev Optimistic period for new agent roots in LightManager\nuint32 constant AGENT_ROOT_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Timeout between the agent root could be proposed and resolved in LightManager\nuint32 constant AGENT_ROOT_PROPOSAL_TIMEOUT = 12 hours;\nuint32 constant BONDING_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Amount of time that the Notary will not be considered active after they won a dispute\nuint32 constant DISPUTE_TIMEOUT_NOTARY = 12 hours;\n/// @dev Amount of time without fresh data from Notaries before contract owner can resolve stuck disputes manually\nuint256 constant FRESH_DATA_TIMEOUT = 4 hours;\n/// @dev Maximum bytes per message = 2 KiB (somewhat arbitrarily set to begin)\nuint256 constant MAX_CONTENT_BYTES = 2 * 2 ** 10;\n/// @dev Maximum value for the summit tip that could be set in GasOracle\nuint256 constant MAX_SUMMIT_TIP = 0.01 ether;\n\n// contracts/libs/Errors.sol\n\n// ══════════════════════════════ INVALID CALLER ═══════════════════════════════\n\nerror CallerNotAgentManager();\nerror CallerNotDestination();\nerror CallerNotInbox();\nerror CallerNotSummit();\n\n// ══════════════════════════════ INCORRECT DATA ═══════════════════════════════\n\nerror IncorrectAttestation();\nerror IncorrectAgentDomain();\nerror IncorrectAgentIndex();\nerror IncorrectAgentProof();\nerror IncorrectAgentRoot();\nerror IncorrectDataHash();\nerror IncorrectDestinationDomain();\nerror IncorrectOriginDomain();\nerror IncorrectSnapshotProof();\nerror IncorrectSnapshotRoot();\nerror IncorrectState();\nerror IncorrectStatesAmount();\nerror IncorrectTipsProof();\nerror IncorrectVersionLength();\n\nerror IncorrectNonce();\nerror IncorrectSender();\nerror IncorrectRecipient();\n\nerror FlagOutOfRange();\nerror IndexOutOfRange();\nerror NonceOutOfRange();\n\nerror OutdatedNonce();\n\nerror UnformattedAttestation();\nerror UnformattedAttestationReport();\nerror UnformattedBaseMessage();\nerror UnformattedCallData();\nerror UnformattedCallDataPrefix();\nerror UnformattedMessage();\nerror UnformattedReceipt();\nerror UnformattedReceiptReport();\nerror UnformattedSignature();\nerror UnformattedSnapshot();\nerror UnformattedState();\nerror UnformattedStateReport();\n\n// ═══════════════════════════════ MERKLE TREES ════════════════════════════════\n\nerror LeafNotProven();\nerror MerkleTreeFull();\nerror NotEnoughLeafs();\nerror TreeHeightTooLow();\n\n// ═════════════════════════════ OPTIMISTIC PERIOD ═════════════════════════════\n\nerror BaseClientOptimisticPeriod();\nerror MessageOptimisticPeriod();\nerror SlashAgentOptimisticPeriod();\nerror WithdrawTipsOptimisticPeriod();\nerror ZeroProofMaturity();\n\n// ═══════════════════════════════ AGENT MANAGER ═══════════════════════════════\n\nerror AgentNotGuard();\nerror AgentNotNotary();\n\nerror AgentCantBeAdded();\nerror AgentNotActive();\nerror AgentNotActiveNorUnstaking();\nerror AgentNotFraudulent();\nerror AgentNotUnstaking();\nerror AgentUnknown();\n\nerror AgentRootNotProposed();\nerror AgentRootTimeoutNotOver();\n\nerror NotStuck();\n\nerror DisputeAlreadyResolved();\nerror DisputeNotOpened();\nerror DisputeTimeoutNotOver();\nerror GuardInDispute();\nerror NotaryInDispute();\n\nerror MustBeSynapseDomain();\nerror SynapseDomainForbidden();\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\nerror AlreadyExecuted();\nerror AlreadyFailed();\nerror DuplicatedSnapshotRoot();\nerror IncorrectMagicValue();\nerror GasLimitTooLow();\nerror GasSuppliedTooLow();\n\n// ══════════════════════════════════ ORIGIN ═══════════════════════════════════\n\nerror ContentLengthTooBig();\nerror EthTransferFailed();\nerror InsufficientEthBalance();\n\n// ════════════════════════════════ GAS ORACLE ═════════════════════════════════\n\nerror LocalGasDataNotSet();\nerror RemoteGasDataNotSet();\n\n// ═══════════════════════════════════ TIPS ════════════════════════════════════\n\nerror SummitTipTooHigh();\nerror TipsClaimMoreThanEarned();\nerror TipsClaimZero();\nerror TipsOverflow();\nerror TipsValueTooLow();\n\n// ════════════════════════════════ MEMORY VIEW ════════════════════════════════\n\nerror IndexedTooMuch();\nerror ViewOverrun();\nerror OccupiedMemory();\nerror UnallocatedMemory();\nerror PrecompileOutOfGas();\n\n// ═════════════════════════════════ MULTICALL ═════════════════════════════════\n\nerror MulticallFailed();\n\n// contracts/libs/TypeCasts.sol\n\nlibrary TypeCasts {\n    // alignment preserving cast\n    function addressToBytes32(address addr) internal pure returns (bytes32) {\n        return bytes32(uint256(uint160(addr)));\n    }\n\n    // alignment preserving cast\n    function bytes32ToAddress(bytes32 buf) internal pure returns (address) {\n        return address(uint160(uint256(buf)));\n    }\n}\n\n// contracts/libs/stack/Number.sol\n\n/// Number is a compact representation of uint256, that is fit into 16 bits\n/// with the maximum relative error under 0.4%.\ntype Number is uint16;\n\nusing NumberLib for Number global;\n\n/// # Number\n/// Library for compact representation of uint256 numbers.\n/// - Number is stored using mantissa and exponent, each occupying 8 bits.\n/// - Numbers under 2**8 are stored as `mantissa` with `exponent = 0xFF`.\n/// - Numbers at least 2**8 are approximated as `(256 + mantissa) \u003c\u003c exponent`\n/// \u003e - `0 \u003c= mantissa \u003c 256`\n/// \u003e - `0 \u003c= exponent \u003c= 247` (`256 * 2**248` doesn't fit into uint256)\n/// # Number stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type  | Bytes |\n/// | ---------- | -------- | ----- | ----- |\n/// | (002..001] | mantissa | uint8 | 1     |\n/// | (001..000] | exponent | uint8 | 1     |\n\nlibrary NumberLib {\n    /// @dev Amount of bits to shift to mantissa field\n    uint16 private constant SHIFT_MANTISSA = 8;\n\n    /// @notice For bwad math (binary wad) we use 2**64 as \"wad\" unit.\n    /// @dev We are using not using 10**18 as wad, because it is not stored precisely in NumberLib.\n    uint256 internal constant BWAD_SHIFT = 64;\n    uint256 internal constant BWAD = 1 \u003c\u003c BWAD_SHIFT;\n    /// @notice ~0.1% in bwad units.\n    uint256 internal constant PER_MILLE_SHIFT = BWAD_SHIFT - 10;\n    uint256 internal constant PER_MILLE = 1 \u003c\u003c PER_MILLE_SHIFT;\n\n    /// @notice Compresses uint256 number into 16 bits.\n    function compress(uint256 value) internal pure returns (Number) {\n        // Find `msb` such as `2**msb \u003c= value \u003c 2**(msb + 1)`\n        uint256 msb = mostSignificantBit(value);\n        // We want to preserve 9 bits of precision.\n        // The highest bit is always 1, so we can skip it.\n        // The remaining 8 highest bits are stored as mantissa.\n        if (msb \u003c 8) {\n            // Value is less than 2**8, so we can use value as mantissa with \"-1\" exponent.\n            return _encode(uint8(value), 0xFF);\n        } else {\n            // We use `msb - 8` as exponent otherwise. Note that `exponent \u003e= 0`.\n            unchecked {\n                uint256 exponent = msb - 8;\n                // Shifting right by `msb-8` bits will shift the \"remaining 8 highest bits\" into the 8 lowest bits.\n                // uint8() will truncate the highest bit.\n                return _encode(uint8(value \u003e\u003e exponent), uint8(exponent));\n            }\n        }\n    }\n\n    /// @notice Decompresses 16 bits number into uint256.\n    /// @dev The outcome is an approximation of the original number: `(value - value / 256) \u003c number \u003c= value`.\n    function decompress(Number number) internal pure returns (uint256 value) {\n        // Isolate 8 highest bits as the mantissa.\n        uint256 mantissa = Number.unwrap(number) \u003e\u003e SHIFT_MANTISSA;\n        // This will truncate the highest bits, leaving only the exponent.\n        uint256 exponent = uint8(Number.unwrap(number));\n        if (exponent == 0xFF) {\n            return mantissa;\n        } else {\n            unchecked {\n                return (256 + mantissa) \u003c\u003c (exponent);\n            }\n        }\n    }\n\n    /// @dev Returns the most significant bit of `x`\n    /// https://solidity-by-example.org/bitwise/\n    function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\n        // To find `msb` we determine it bit by bit, starting from the highest one.\n        // `0 \u003c= msb \u003c= 255`, so we start from the highest bit, 1\u003c\u003c7 == 128.\n        // If `x` is at least 2**128, then the highest bit of `x` is at least 128.\n        // solhint-disable no-inline-assembly\n        assembly {\n            // `f` is set to 1\u003c\u003c7 if `x \u003e= 2**128` and to 0 otherwise.\n            let f := shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\n            // If `x \u003e= 2**128` then set `msb` highest bit to 1 and shift `x` right by 128.\n            // Otherwise, `msb` remains 0 and `x` remains unchanged.\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        // `x` is now at most 2**128 - 1. Continue the same way, the next highest bit is 1\u003c\u003c6 == 64.\n        assembly {\n            // `f` is set to 1\u003c\u003c6 if `x \u003e= 2**64` and to 0 otherwise.\n            let f := shl(6, gt(x, 0xFFFFFFFFFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c5 if `x \u003e= 2**32` and to 0 otherwise.\n            let f := shl(5, gt(x, 0xFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c4 if `x \u003e= 2**16` and to 0 otherwise.\n            let f := shl(4, gt(x, 0xFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c3 if `x \u003e= 2**8` and to 0 otherwise.\n            let f := shl(3, gt(x, 0xFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c2 if `x \u003e= 2**4` and to 0 otherwise.\n            let f := shl(2, gt(x, 0xF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c1 if `x \u003e= 2**2` and to 0 otherwise.\n            let f := shl(1, gt(x, 0x3))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1 if `x \u003e= 2**1` and to 0 otherwise.\n            let f := gt(x, 0x1)\n            msb := or(msb, f)\n        }\n    }\n\n    /// @dev Wraps (mantissa, exponent) pair into Number.\n    function _encode(uint8 mantissa, uint8 exponent) private pure returns (Number) {\n        // Casts below are upcasts, so they are safe.\n        return Number.wrap(uint16(mantissa) \u003c\u003c SHIFT_MANTISSA | uint16(exponent));\n    }\n}\n\n// contracts/libs/stack/Request.sol\n\n/// Request is encoded data with \"message execution request\".\ntype Request is uint192;\n\nusing RequestLib for Request global;\n\n/// Library for formatting _the request part_ of _the base messages_.\n/// - Request represents a message sender requirements for the message execution on the destination chain.\n/// - Request occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n/// \u003e gasDrop field is included for future compatibility and is ignored at the moment.\n///\n/// # Request stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type   | Bytes | Description                                          |\n/// | ---------- | -------- | ------ | ----- | ---------------------------------------------------- |\n/// | (024..012] | gasDrop  | uint96 | 12    | Minimum amount of gas token to drop to the recipient |\n/// | (012..004] | gasLimit | uint64 | 8     | Minimum amount of gas units to supply for execution  |\n/// | (004..000] | version  | uint32 | 4     | Base message version to pass to the recipient        |\n\nlibrary RequestLib {\n    /// @dev Amount of bits to shift to gasDrop field\n    uint192 private constant SHIFT_GAS_DROP = 12 * 8;\n    /// @dev Amount of bits to shift to gasLimit field\n    uint192 private constant SHIFT_GAS_LIMIT = 4 * 8;\n\n    /// @notice Returns an encoded request with the given fields\n    /// @param gasDrop_     Minimum amount of gas token to drop to the recipient (ignored at the moment)\n    /// @param gasLimit_    Minimum amount of gas units to supply for execution\n    /// @param version_     Base message version to pass to the recipient\n    function encodeRequest(uint96 gasDrop_, uint64 gasLimit_, uint32 version_) internal pure returns (Request) {\n        // Casts below are upcasts, so they are safe\n        return Request.wrap(uint192(gasDrop_) \u003c\u003c SHIFT_GAS_DROP | uint192(gasLimit_) \u003c\u003c SHIFT_GAS_LIMIT | version_);\n    }\n\n    /// @notice Wraps the padded encoded request into a Request-typed value.\n    /// @dev The \"padded\" request is simply an encoded request casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded requests\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedRequest) internal pure returns (Request) {\n        // Casting to uint192 will truncate the highest bits, which is the behavior we want\n        return Request.wrap(uint192(paddedRequest));\n    }\n\n    /// @notice Returns the requested of gas token to drop to the recipient.\n    function gasDrop(Request request) internal pure returns (uint96) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return uint96(Request.unwrap(request) \u003e\u003e SHIFT_GAS_DROP);\n    }\n\n    /// @notice Returns the requested minimum amount of gas units to supply for execution.\n    function gasLimit(Request request) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Request.unwrap(request) \u003e\u003e SHIFT_GAS_LIMIT);\n    }\n\n    /// @notice Returns the requested base message version to pass to the recipient.\n    function version(Request request) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Request.unwrap(request));\n    }\n}\n\n// node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        require(value \u003c= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        require(value \u003c= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        require(value \u003c= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value \u003c= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        require(value \u003c= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        require(value \u003c= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        require(value \u003c= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        require(value \u003c= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        require(value \u003c= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        require(value \u003c= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        require(value \u003c= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        require(value \u003c= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        require(value \u003c= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        require(value \u003c= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        require(value \u003c= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value \u003c= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        require(value \u003c= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        require(value \u003c= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        require(value \u003c= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value \u003c= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        require(value \u003c= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        require(value \u003c= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        require(value \u003c= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value \u003c= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        require(value \u003c= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        require(value \u003c= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        require(value \u003c= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value \u003c= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        require(value \u003c= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value \u003c= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value \u003c= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     *\n     * _Available since v3.0._\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value \u003e= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     *\n     * _Available since v3.0._\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value \u003c= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     *\n     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length \u003e 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance \u003e= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance \u003e= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length \u003e 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n\n// contracts/base/MultiCallable.sol\n\n/// @notice Collection of Multicall utilities. Fork of Multicall3:\n/// https://github.com/mds1/multicall/blob/master/src/Multicall3.sol\nabstract contract MultiCallable {\n    struct Call {\n        bool allowFailure;\n        bytes callData;\n    }\n\n    struct Result {\n        bool success;\n        bytes returnData;\n    }\n\n    /// @notice Aggregates a few calls to this contract into one multicall without modifying `msg.sender`.\n    function multicall(Call[] calldata calls) external returns (Result[] memory callResults) {\n        uint256 amount = calls.length;\n        callResults = new Result[](amount);\n        Call calldata call_;\n        for (uint256 i = 0; i \u003c amount;) {\n            call_ = calls[i];\n            Result memory result = callResults[i];\n            // We perform a delegate call to ourselves here. Delegate call does not modify `msg.sender`, so\n            // this will have the same effect as if `msg.sender` performed all the calls themselves one by one.\n            // solhint-disable-next-line avoid-low-level-calls\n            (result.success, result.returnData) = address(this).delegatecall(call_.callData);\n            // solhint-disable-next-line no-inline-assembly\n            assembly {\n                // Revert if the call fails and failure is not allowed\n                // `allowFailure := calldataload(call_)` and `success := mload(result)`\n                if iszero(or(calldataload(call_), mload(result))) {\n                    // Revert with `0x4d6a2328` (function selector for `MulticallFailed()`)\n                    mstore(0x00, 0x4d6a232800000000000000000000000000000000000000000000000000000000)\n                    revert(0x00, 0x04)\n                }\n            }\n            unchecked {\n                ++i;\n            }\n        }\n    }\n}\n\n// contracts/base/Version.sol\n\n/**\n * @title Versioned\n * @notice Version getter for contracts. Doesn't use any storage slots, meaning\n * it will never cause any troubles with the upgradeable contracts. For instance, this contract\n * can be added or removed from the inheritance chain without shifting the storage layout.\n */\nabstract contract Versioned {\n    /**\n     * @notice Struct that is mimicking the storage layout of a string with 32 bytes or less.\n     * Length is limited by 32, so the whole string payload takes two memory words:\n     * @param length    String length\n     * @param data      String characters\n     */\n    struct _ShortString {\n        uint256 length;\n        bytes32 data;\n    }\n\n    /// @dev Length of the \"version string\"\n    uint256 private immutable _length;\n    /// @dev Bytes representation of the \"version string\".\n    /// Strings with length over 32 are not supported!\n    bytes32 private immutable _data;\n\n    constructor(string memory version_) {\n        _length = bytes(version_).length;\n        if (_length \u003e 32) revert IncorrectVersionLength();\n        // bytes32 is left-aligned =\u003e this will store the byte representation of the string\n        // with the trailing zeroes to complete the 32-byte word\n        _data = bytes32(bytes(version_));\n    }\n\n    function version() external view returns (string memory versionString) {\n        // Load the immutable values to form the version string\n        _ShortString memory str = _ShortString(_length, _data);\n        // The only way to do this cast is doing some dirty assembly\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            versionString := str\n        }\n    }\n}\n\n// contracts/libs/ChainContext.sol\n\n/// @notice Library for accessing chain context variables as tightly packed integers.\n/// Messaging contracts should rely on this library for accessing chain context variables\n/// instead of doing the casting themselves.\nlibrary ChainContext {\n    using SafeCast for uint256;\n\n    /// @notice Returns the current block number as uint40.\n    /// @dev Reverts if block number is greater than 40 bits, which is not supposed to happen\n    /// until the block.timestamp overflows (assuming block time is at least 1 second).\n    function blockNumber() internal view returns (uint40) {\n        return block.number.toUint40();\n    }\n\n    /// @notice Returns the current block timestamp as uint40.\n    /// @dev Reverts if block timestamp is greater than 40 bits, which is\n    /// supposed to happen approximately in year 36835.\n    function blockTimestamp() internal view returns (uint40) {\n        return block.timestamp.toUint40();\n    }\n\n    /// @notice Returns the chain id as uint32.\n    /// @dev Reverts if chain id is greater than 32 bits, which is not\n    /// supposed to happen in production.\n    function chainId() internal view returns (uint32) {\n        return block.chainid.toUint32();\n    }\n}\n\n// contracts/libs/Structures.sol\n\n// Here we define common enums and structures to enable their easier reusing later.\n\n// ═══════════════════════════════ AGENT STATUS ════════════════════════════════\n\n/// @dev Potential statuses for the off-chain bonded agent:\n/// - Unknown: never provided a bond =\u003e signature not valid\n/// - Active: has a bond in BondingManager =\u003e signature valid\n/// - Unstaking: has a bond in BondingManager, initiated the unstaking =\u003e signature not valid\n/// - Resting: used to have a bond in BondingManager, successfully unstaked =\u003e signature not valid\n/// - Fraudulent: proven to commit fraud, value in Merkle Tree not updated =\u003e signature not valid\n/// - Slashed: proven to commit fraud, value in Merkle Tree was updated =\u003e signature not valid\n/// Unstaked agent could later be added back to THE SAME domain by staking a bond again.\n/// Honest agent: Unknown -\u003e Active -\u003e unstaking -\u003e Resting -\u003e Active ...\n/// Malicious agent: Unknown -\u003e Active -\u003e Fraudulent -\u003e Slashed\n/// Malicious agent: Unknown -\u003e Active -\u003e Unstaking -\u003e Fraudulent -\u003e Slashed\nenum AgentFlag {\n    Unknown,\n    Active,\n    Unstaking,\n    Resting,\n    Fraudulent,\n    Slashed\n}\n\n/// @notice Struct for storing an agent in the BondingManager contract.\nstruct AgentStatus {\n    AgentFlag flag;\n    uint32 domain;\n    uint32 index;\n}\n// 184 bits available for tight packing\n\nusing StructureUtils for AgentStatus global;\n\n/// @notice Potential statuses of an agent in terms of being in dispute\n/// - None: agent is not in dispute\n/// - Pending: agent is in unresolved dispute\n/// - Slashed: agent was in dispute that lead to agent being slashed\n/// Note: agent who won the dispute has their status reset to None\nenum DisputeFlag {\n    None,\n    Pending,\n    Slashed\n}\n\n/// @notice Struct for storing dispute status of an agent.\n/// @param flag         Dispute flag: None/Pending/Slashed.\n/// @param openedAt     Timestamp when the latest agent dispute was opened (zero if not opened).\n/// @param resolvedAt   Timestamp when the latest agent dispute was resolved (zero if not resolved).\nstruct DisputeStatus {\n    DisputeFlag flag;\n    uint40 openedAt;\n    uint40 resolvedAt;\n}\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\n/// @notice Struct representing the status of Destination contract.\n/// @param snapRootTime     Timestamp when latest snapshot root was accepted\n/// @param agentRootTime    Timestamp when latest agent root was accepted\n/// @param notaryIndex      Index of Notary who signed the latest agent root\nstruct DestinationStatus {\n    uint40 snapRootTime;\n    uint40 agentRootTime;\n    uint32 notaryIndex;\n}\n\n// ═══════════════════════════════ EXECUTION HUB ═══════════════════════════════\n\n/// @notice Potential statuses of the message in Execution Hub.\n/// - None: there hasn't been a valid attempt to execute the message yet\n/// - Failed: there was a valid attempt to execute the message, but recipient reverted\n/// - Success: there was a valid attempt to execute the message, and recipient did not revert\n/// Note: message can be executed until its status is Success\nenum MessageStatus {\n    None,\n    Failed,\n    Success\n}\n\nlibrary StructureUtils {\n    /// @notice Checks that Agent is Active\n    function verifyActive(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active) {\n            revert AgentNotActive();\n        }\n    }\n\n    /// @notice Checks that Agent is Unstaking\n    function verifyUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Unstaking) {\n            revert AgentNotUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Active or Unstaking\n    function verifyActiveUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active \u0026\u0026 status.flag != AgentFlag.Unstaking) {\n            revert AgentNotActiveNorUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Fraudulent\n    function verifyFraudulent(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Fraudulent) {\n            revert AgentNotFraudulent();\n        }\n    }\n\n    /// @notice Checks that Agent is not Unknown\n    function verifyKnown(AgentStatus memory status) internal pure {\n        if (status.flag == AgentFlag.Unknown) {\n            revert AgentUnknown();\n        }\n    }\n}\n\n// contracts/libs/memory/MemView.sol\n\n/// @dev MemView is an untyped view over a portion of memory to be used instead of `bytes memory`\ntype MemView is uint256;\n\n/// @dev Attach library functions to MemView\nusing MemViewLib for MemView global;\n\n/// @notice Library for operations with the memory views.\n/// Forked from https://github.com/summa-tx/memview-sol with several breaking changes:\n/// - The codebase is ported to Solidity 0.8\n/// - Custom errors are added\n/// - The runtime type checking is replaced with compile-time check provided by User-Defined Value Types\n///   https://docs.soliditylang.org/en/latest/types.html#user-defined-value-types\n/// - uint256 is used as the underlying type for the \"memory view\" instead of bytes29.\n///   It is wrapped into MemView custom type in order not to be confused with actual integers.\n/// - Therefore the \"type\" field is discarded, allowing to allocate 16 bytes for both view location and length\n/// - The documentation is expanded\n/// - Library functions unused by the rest of the codebase are removed\n//  - Very pretty code separators are added :)\nlibrary MemViewLib {\n    /// @notice Stack layout for uint256 (from highest bits to lowest)\n    /// (32 .. 16]      loc     16 bytes    Memory address of underlying bytes\n    /// (16 .. 00]      len     16 bytes    Length of underlying bytes\n\n    // ═══════════════════════════════════════════ BUILDING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Instantiate a new untyped memory view. This should generally not be called directly.\n     * Prefer `ref` wherever possible.\n     * @param loc_          The memory address\n     * @param len_          The length\n     * @return The new view with the specified location and length\n     */\n    function build(uint256 loc_, uint256 len_) internal pure returns (MemView) {\n        uint256 end_ = loc_ + len_;\n        // Make sure that a view is not constructed that points to unallocated memory\n        // as this could be indicative of a buffer overflow attack\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            if gt(end_, mload(0x40)) { end_ := 0 }\n        }\n        if (end_ == 0) {\n            revert UnallocatedMemory();\n        }\n        return _unsafeBuildUnchecked(loc_, len_);\n    }\n\n    /**\n     * @notice Instantiate a memory view from a byte array.\n     * @dev Note that due to Solidity memory representation, it is not possible to\n     * implement a deref, as the `bytes` type stores its len in memory.\n     * @param arr           The byte array\n     * @return The memory view over the provided byte array\n     */\n    function ref(bytes memory arr) internal pure returns (MemView) {\n        uint256 len_ = arr.length;\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 loc_;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // We add 0x20, so that the view starts exactly where the array data starts\n            loc_ := add(arr, 0x20)\n        }\n        return build(loc_, len_);\n    }\n\n    // ════════════════════════════════════════════ CLONING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to the new memory.\n     * @param memView       The memory view\n     * @return arr          The cloned byte array\n     */\n    function clone(MemView memView) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        unchecked {\n            _unsafeCopyTo(memView, ptr + 0x20);\n        }\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 len_ = memView.len();\n        uint256 footprint_ = memView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    /**\n     * @notice Copies all views, joins them into a new bytearray.\n     * @param memViews      The memory views\n     * @return arr          The new byte array with joined data behind the given views\n     */\n    function join(MemView[] memory memViews) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        MemView newView;\n        unchecked {\n            newView = _unsafeJoin(memViews, ptr + 0x20);\n        }\n        uint256 len_ = newView.len();\n        uint256 footprint_ = newView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    // ══════════════════════════════════════════ INSPECTING MEMORY VIEW ═══════════════════════════════════════════════\n\n    /**\n     * @notice Returns the memory address of the underlying bytes.\n     * @param memView       The memory view\n     * @return loc_         The memory address\n     */\n    function loc(MemView memView) internal pure returns (uint256 loc_) {\n        // loc is stored in the highest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u003e\u003e 128;\n    }\n\n    /**\n     * @notice Returns the number of bytes of the view.\n     * @param memView       The memory view\n     * @return len_         The length of the view\n     */\n    function len(MemView memView) internal pure returns (uint256 len_) {\n        // len is stored in the lowest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u0026 type(uint128).max;\n    }\n\n    /**\n     * @notice Returns the endpoint of `memView`.\n     * @param memView       The memory view\n     * @return end_         The endpoint of `memView`\n     */\n    function end(MemView memView) internal pure returns (uint256 end_) {\n        // The endpoint never overflows uint128, let alone uint256, so we could use unchecked math here\n        unchecked {\n            return memView.loc() + memView.len();\n        }\n    }\n\n    /**\n     * @notice Returns the number of memory words this memory view occupies, rounded up.\n     * @param memView       The memory view\n     * @return words_       The number of memory words\n     */\n    function words(MemView memView) internal pure returns (uint256 words_) {\n        // returning ceil(length / 32.0)\n        unchecked {\n            return (memView.len() + 31) \u003e\u003e 5;\n        }\n    }\n\n    /**\n     * @notice Returns the in-memory footprint of a fresh copy of the view.\n     * @param memView       The memory view\n     * @return footprint_   The in-memory footprint of a fresh copy of the view.\n     */\n    function footprint(MemView memView) internal pure returns (uint256 footprint_) {\n        // words() * 32\n        return memView.words() \u003c\u003c 5;\n    }\n\n    // ════════════════════════════════════════════ HASHING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the keccak256 hash of the underlying memory\n     * @param memView       The memory view\n     * @return digest       The keccak256 hash of the underlying memory\n     */\n    function keccak(MemView memView) internal pure returns (bytes32 digest) {\n        uint256 loc_ = memView.loc();\n        uint256 len_ = memView.len();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            digest := keccak256(loc_, len_)\n        }\n    }\n\n    /**\n     * @notice Adds a salt to the keccak256 hash of the underlying data and returns the keccak256 hash of the\n     * resulting data.\n     * @param memView       The memory view\n     * @return digestSalted keccak256(salt, keccak256(memView))\n     */\n    function keccakSalted(MemView memView, bytes32 salt) internal pure returns (bytes32 digestSalted) {\n        return keccak256(bytes.concat(salt, memView.keccak()));\n    }\n\n    // ════════════════════════════════════════════ SLICING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Safe slicing without memory modification.\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the given index\n     */\n    function slice(MemView memView, uint256 index_, uint256 len_) internal pure returns (MemView) {\n        uint256 loc_ = memView.loc();\n        // Ensure it doesn't overrun the view\n        if (loc_ + index_ + len_ \u003e memView.end()) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // loc_ + index_ \u003c= memView.end()\n            return build({loc_: loc_ + index_, len_: len_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing bytes from `index` to end(memView).\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @return The new view for the slice starting from the given index until the initial view endpoint\n     */\n    function sliceFrom(MemView memView, uint256 index_) internal pure returns (MemView) {\n        uint256 len_ = memView.len();\n        // Ensure it doesn't overrun the view\n        if (index_ \u003e len_) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // index_ \u003c= len_ =\u003e memView.loc() + index_ \u003c= memView.loc() + memView.len() == memView.end()\n            return build({loc_: memView.loc() + index_, len_: len_ - index_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the first `len` bytes.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the initial view beginning\n     */\n    function prefix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        return memView.slice({index_: 0, len_: len_});\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the last `len` byte.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length until the initial view endpoint\n     */\n    function postfix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        uint256 viewLen = memView.len();\n        // Ensure it doesn't overrun the view\n        if (len_ \u003e viewLen) {\n            revert ViewOverrun();\n        }\n        // Could do the unchecked math due to the check above\n        uint256 index_;\n        unchecked {\n            index_ = viewLen - len_;\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // len_ \u003c= memView.len() =\u003e memView.loc() \u003c= loc_ \u003c= memView.end()\n            return build({loc_: memView.loc() + viewLen - len_, len_: len_});\n        }\n    }\n\n    // ═══════════════════════════════════════════ INDEXING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Load up to 32 bytes from the view onto the stack.\n     * @dev Returns a bytes32 with only the `bytes_` HIGHEST bytes set.\n     * This can be immediately cast to a smaller fixed-length byte array.\n     * To automatically cast to an integer, use `indexUint`.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return result       The 32 byte result having only `bytes_` highest bytes set\n     */\n    function index(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (bytes32 result) {\n        if (bytes_ == 0) {\n            return bytes32(0);\n        }\n        // Can't load more than 32 bytes to the stack in one go\n        if (bytes_ \u003e 32) {\n            revert IndexedTooMuch();\n        }\n        // The last indexed byte should be within view boundaries\n        if (index_ + bytes_ \u003e memView.len()) {\n            revert ViewOverrun();\n        }\n        uint256 bitLength = bytes_ \u003c\u003c 3; // bytes_ * 8\n        uint256 loc_ = memView.loc();\n        // Get a mask with `bitLength` highest bits set\n        uint256 mask;\n        // 0x800...00 binary representation is 100...00\n        // sar stands for \"signed arithmetic shift\": https://en.wikipedia.org/wiki/Arithmetic_shift\n        // sar(N-1, 100...00) = 11...100..00, with exactly N highest bits set to 1\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            mask := sar(sub(bitLength, 1), 0x8000000000000000000000000000000000000000000000000000000000000000)\n        }\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load a full word using index offset, and apply mask to ignore non-relevant bytes\n            result := and(mload(add(loc_, index_)), mask)\n        }\n    }\n\n    /**\n     * @notice Parse an unsigned integer from the view at `index`.\n     * @dev Requires that the view have \u003e= `bytes_` bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return The unsigned integer\n     */\n    function indexUint(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (uint256) {\n        bytes32 indexedBytes = memView.index(index_, bytes_);\n        // `index()` returns left-aligned `bytes_`, while integers are right-aligned\n        // Shifting here to right-align with the full 32 bytes word: need to shift right `(32 - bytes_)` bytes\n        unchecked {\n            // memView.index() reverts when bytes_ \u003e 32, thus unchecked math\n            return uint256(indexedBytes) \u003e\u003e ((32 - bytes_) \u003c\u003c 3);\n        }\n    }\n\n    /**\n     * @notice Parse an address from the view at `index`.\n     * @dev Requires that the view have \u003e= 20 bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @return The address\n     */\n    function indexAddress(MemView memView, uint256 index_) internal pure returns (address) {\n        // index 20 bytes as `uint160`, and then cast to `address`\n        return address(uint160(memView.indexUint(index_, 20)));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns a memory view over the specified memory location\n    /// without checking if it points to unallocated memory.\n    function _unsafeBuildUnchecked(uint256 loc_, uint256 len_) private pure returns (MemView) {\n        // There is no scenario where loc or len would overflow uint128, so we omit this check.\n        // We use the highest 128 bits to encode the location and the lowest 128 bits to encode the length.\n        return MemView.wrap((loc_ \u003c\u003c 128) | len_);\n    }\n\n    /**\n     * @notice Copy the view to a location, return an unsafe memory reference\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memView       The memory view\n     * @param newLoc        The new location to copy the underlying view data\n     * @return The memory view over the unsafe memory with the copied underlying data\n     */\n    function _unsafeCopyTo(MemView memView, uint256 newLoc) private view returns (MemView) {\n        uint256 len_ = memView.len();\n        uint256 oldLoc = memView.loc();\n\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (newLoc \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        bool res;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // use the identity precompile (0x04) to copy\n            res := staticcall(gas(), 0x04, oldLoc, len_, newLoc, len_)\n        }\n        if (!res) revert PrecompileOutOfGas();\n        return _unsafeBuildUnchecked({loc_: newLoc, len_: len_});\n    }\n\n    /**\n     * @notice Join the views in memory, return an unsafe reference to the memory.\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memViews      The memory views\n     * @return The conjoined view pointing to the new memory\n     */\n    function _unsafeJoin(MemView[] memory memViews, uint256 location) private view returns (MemView) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (location \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        // Copy the views to the specified location one by one, by tracking the amount of copied bytes so far\n        uint256 offset = 0;\n        for (uint256 i = 0; i \u003c memViews.length;) {\n            MemView memView = memViews[i];\n            // We can use the unchecked math here as location + sum(view.length) will never overflow uint256\n            unchecked {\n                _unsafeCopyTo(memView, location + offset);\n                offset += memView.len();\n                ++i;\n            }\n        }\n        return _unsafeBuildUnchecked({loc_: location, len_: offset});\n    }\n}\n\n// contracts/libs/merkle/MerkleMath.sol\n\nlibrary MerkleMath {\n    // ═════════════════════════════════════════ BASIC MERKLE CALCULATIONS ═════════════════════════════════════════════\n\n    /**\n     * @notice Calculates the merkle root for the given leaf and merkle proof.\n     * @dev Will revert if proof length exceeds the tree height.\n     * @param index     Index of `leaf` in tree\n     * @param leaf      Leaf of the merkle tree\n     * @param proof     Proof of inclusion of `leaf` in the tree\n     * @param height    Height of the merkle tree\n     * @return root_    Calculated Merkle Root\n     */\n    function proofRoot(uint256 index, bytes32 leaf, bytes32[] memory proof, uint256 height)\n        internal\n        pure\n        returns (bytes32 root_)\n    {\n        // Proof length could not exceed the tree height\n        uint256 proofLen = proof.length;\n        if (proofLen \u003e height) revert TreeHeightTooLow();\n        root_ = leaf;\n        /// @dev Apply unchecked to all ++h operations\n        unchecked {\n            // Go up the tree levels from the leaf following the proof\n            for (uint256 h = 0; h \u003c proofLen; ++h) {\n                // Get a sibling node on current level: this is proof[h]\n                root_ = getParent(root_, proof[h], index, h);\n            }\n            // Go up to the root: the remaining siblings are EMPTY\n            for (uint256 h = proofLen; h \u003c height; ++h) {\n                root_ = getParent(root_, bytes32(0), index, h);\n            }\n        }\n    }\n\n    /**\n     * @notice Calculates the parent of a node on the path from one of the leafs to root.\n     * @param node          Node on a path from tree leaf to root\n     * @param sibling       Sibling for a given node\n     * @param leafIndex     Index of the tree leaf\n     * @param nodeHeight    \"Level height\" for `node` (ZERO for leafs, ORIGIN_TREE_HEIGHT for root)\n     */\n    function getParent(bytes32 node, bytes32 sibling, uint256 leafIndex, uint256 nodeHeight)\n        internal\n        pure\n        returns (bytes32 parent)\n    {\n        // Index for `node` on its \"tree level\" is (leafIndex / 2**height)\n        // \"Left child\" has even index, \"right child\" has odd index\n        if ((leafIndex \u003e\u003e nodeHeight) \u0026 1 == 0) {\n            // Left child\n            return getParent(node, sibling);\n        } else {\n            // Right child\n            return getParent(sibling, node);\n        }\n    }\n\n    /// @notice Calculates the parent of tow nodes in the merkle tree.\n    /// @dev We use implementation with H(0,0) = 0\n    /// This makes EVERY empty node in the tree equal to ZERO,\n    /// saving us from storing H(0,0), H(H(0,0), H(0, 0)), and so on\n    /// @param leftChild    Left child of the calculated node\n    /// @param rightChild   Right child of the calculated node\n    /// @return parent      Value for the node having above mentioned children\n    function getParent(bytes32 leftChild, bytes32 rightChild) internal pure returns (bytes32 parent) {\n        if (leftChild == bytes32(0) \u0026\u0026 rightChild == bytes32(0)) {\n            return 0;\n        } else {\n            return keccak256(bytes.concat(leftChild, rightChild));\n        }\n    }\n\n    // ════════════════════════════════ ROOT/PROOF CALCULATION FOR A LIST OF LEAFS ═════════════════════════════════════\n\n    /**\n     * @notice Calculates merkle root for a list of given leafs.\n     * Merkle Tree is constructed by padding the list with ZERO values for leafs until list length is `2**height`.\n     * Merkle Root is calculated for the constructed tree, and then saved in `leafs[0]`.\n     * \u003e Note:\n     * \u003e - `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * \u003e - Caller is expected not to reuse `hashes` list after the call, and only use `leafs[0]` value,\n     * which is guaranteed to contain the calculated merkle root.\n     * \u003e - root is calculated using the `H(0,0) = 0` Merkle Tree implementation. See MerkleTree.sol for details.\n     * @dev Amount of leaves should be at most `2**height`\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param height    Height of the Merkle Tree to construct\n     */\n    function calculateRoot(bytes32[] memory hashes, uint256 height) internal pure {\n        uint256 levelLength = hashes.length;\n        // Amount of hashes could not exceed amount of leafs in tree with the given height\n        if (levelLength \u003e (1 \u003c\u003c height)) revert TreeHeightTooLow();\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\": the amount of iterations for the for loop above.\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n            }\n        }\n    }\n\n    /**\n     * @notice Generates a proof of inclusion of a leaf in the list. If the requested index is outside\n     * of the list range, generates a proof of inclusion for an empty leaf (proof of non-inclusion).\n     * The Merkle Tree is constructed by padding the list with ZERO values until list length is a power of two\n     * __AND__ index is in the extended list range. For example:\n     *  - `hashes.length == 6` and `0 \u003c= index \u003c= 7` will \"extend\" the list to 8 entries.\n     *  - `hashes.length == 6` and `7 \u003c index \u003c= 15` will \"extend\" the list to 16 entries.\n     * \u003e Note: `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * Caller is expected not to reuse `hashes` list after the call.\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param index     Leaf index to generate the proof for\n     * @return proof    Generated merkle proof\n     */\n    function calculateProof(bytes32[] memory hashes, uint256 index) internal pure returns (bytes32[] memory proof) {\n        // Use only meaningful values for the shortened proof\n        // Check if index is within the list range (we want to generates proofs for outside leafs as well)\n        uint256 height = getHeight(index \u003c hashes.length ? hashes.length : (index + 1));\n        proof = new bytes32[](height);\n        uint256 levelLength = hashes.length;\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Use sibling for the merkle proof; `index^1` is index of our sibling\n                proof[h] = (index ^ 1 \u003c levelLength) ? hashes[index ^ 1] : bytes32(0);\n\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\"\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n                // Traverse to parent node\n                index \u003e\u003e= 1;\n            }\n        }\n    }\n\n    /// @notice Returns the height of the tree having a given amount of leafs.\n    function getHeight(uint256 leafs) internal pure returns (uint256 height) {\n        uint256 amount = 1;\n        while (amount \u003c leafs) {\n            unchecked {\n                ++height;\n            }\n            amount \u003c\u003c= 1;\n        }\n    }\n}\n\n// contracts/libs/stack/GasData.sol\n\n/// GasData in encoded data with \"basic information about gas prices\" for some chain.\ntype GasData is uint96;\n\nusing GasDataLib for GasData global;\n\n/// ChainGas is encoded data with given chain's \"basic information about gas prices\".\ntype ChainGas is uint128;\n\nusing GasDataLib for ChainGas global;\n\n/// Library for encoding and decoding GasData and ChainGas structs.\n/// # GasData\n/// `GasData` is a struct to store the \"basic information about gas prices\", that could\n/// be later used to approximate the cost of a message execution, and thus derive the\n/// minimal tip values for sending a message to the chain.\n/// \u003e - `GasData` is supposed to be cached by `GasOracle` contract, allowing to store the\n/// \u003e approximates instead of the exact values, and thus save on storage costs.\n/// \u003e - For instance, if `GasOracle` only updates the values on +- 10% change, having an\n/// \u003e 0.4% error on the approximates would be acceptable.\n/// `GasData` is supposed to be included in the Origin's state, which are synced across\n/// chains using Agent-signed snapshots and attestations.\n/// ## GasData stack layout (from highest bits to lowest)\n///\n/// | Position   | Field        | Type   | Bytes | Description                                         |\n/// | ---------- | ------------ | ------ | ----- | --------------------------------------------------- |\n/// | (012..010] | gasPrice     | uint16 | 2     | Gas price for the chain (in Wei per gas unit)       |\n/// | (010..008] | dataPrice    | uint16 | 2     | Calldata price (in Wei per byte of content)         |\n/// | (008..006] | execBuffer   | uint16 | 2     | Tx fee safety buffer for message execution (in Wei) |\n/// | (006..004] | amortAttCost | uint16 | 2     | Amortized cost for attestation submission (in Wei)  |\n/// | (004..002] | etherPrice   | uint16 | 2     | Chain's Ether Price / Mainnet Ether Price (in BWAD) |\n/// | (002..000] | markup       | uint16 | 2     | Markup for the message execution (in BWAD)          |\n/// \u003e See Number.sol for more details on `Number` type and BWAD (binary WAD) math.\n///\n/// ## ChainGas stack layout (from highest bits to lowest)\n///\n/// | Position   | Field   | Type   | Bytes | Description      |\n/// | ---------- | ------- | ------ | ----- | ---------------- |\n/// | (016..004] | gasData | uint96 | 12    | Chain's gas data |\n/// | (004..000] | domain  | uint32 | 4     | Chain's domain   |\nlibrary GasDataLib {\n    /// @dev Amount of bits to shift to gasPrice field\n    uint96 private constant SHIFT_GAS_PRICE = 10 * 8;\n    /// @dev Amount of bits to shift to dataPrice field\n    uint96 private constant SHIFT_DATA_PRICE = 8 * 8;\n    /// @dev Amount of bits to shift to execBuffer field\n    uint96 private constant SHIFT_EXEC_BUFFER = 6 * 8;\n    /// @dev Amount of bits to shift to amortAttCost field\n    uint96 private constant SHIFT_AMORT_ATT_COST = 4 * 8;\n    /// @dev Amount of bits to shift to etherPrice field\n    uint96 private constant SHIFT_ETHER_PRICE = 2 * 8;\n\n    /// @dev Amount of bits to shift to gasData field\n    uint128 private constant SHIFT_GAS_DATA = 4 * 8;\n\n    // ═════════════════════════════════════════════════ GAS DATA ══════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded GasData struct with the given fields.\n    /// @param gasPrice_        Gas price for the chain (in Wei per gas unit)\n    /// @param dataPrice_       Calldata price (in Wei per byte of content)\n    /// @param execBuffer_      Tx fee safety buffer for message execution (in Wei)\n    /// @param amortAttCost_    Amortized cost for attestation submission (in Wei)\n    /// @param etherPrice_      Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n    /// @param markup_          Markup for the message execution (in BWAD)\n    function encodeGasData(\n        Number gasPrice_,\n        Number dataPrice_,\n        Number execBuffer_,\n        Number amortAttCost_,\n        Number etherPrice_,\n        Number markup_\n    ) internal pure returns (GasData) {\n        // Number type wraps uint16, so could safely be casted to uint96\n        // forgefmt: disable-next-item\n        return GasData.wrap(\n            uint96(Number.unwrap(gasPrice_)) \u003c\u003c SHIFT_GAS_PRICE |\n            uint96(Number.unwrap(dataPrice_)) \u003c\u003c SHIFT_DATA_PRICE |\n            uint96(Number.unwrap(execBuffer_)) \u003c\u003c SHIFT_EXEC_BUFFER |\n            uint96(Number.unwrap(amortAttCost_)) \u003c\u003c SHIFT_AMORT_ATT_COST |\n            uint96(Number.unwrap(etherPrice_)) \u003c\u003c SHIFT_ETHER_PRICE |\n            uint96(Number.unwrap(markup_))\n        );\n    }\n\n    /// @notice Wraps padded uint256 value into GasData struct.\n    function wrapGasData(uint256 paddedGasData) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(paddedGasData));\n    }\n\n    /// @notice Returns the gas price, in Wei per gas unit.\n    function gasPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_GAS_PRICE));\n    }\n\n    /// @notice Returns the calldata price, in Wei per byte of content.\n    function dataPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_DATA_PRICE));\n    }\n\n    /// @notice Returns the tx fee safety buffer for message execution, in Wei.\n    function execBuffer(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_EXEC_BUFFER));\n    }\n\n    /// @notice Returns the amortized cost for attestation submission, in Wei.\n    function amortAttCost(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_AMORT_ATT_COST));\n    }\n\n    /// @notice Returns the ratio of Chain's Ether Price / Mainnet Ether Price, in BWAD math.\n    function etherPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_ETHER_PRICE));\n    }\n\n    /// @notice Returns the markup for the message execution, in BWAD math.\n    function markup(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data)));\n    }\n\n    // ════════════════════════════════════════════════ CHAIN DATA ═════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded ChainGas struct with the given fields.\n    /// @param gasData_ Chain's gas data\n    /// @param domain_  Chain's domain\n    function encodeChainGas(GasData gasData_, uint32 domain_) internal pure returns (ChainGas) {\n        // GasData type wraps uint96, so could safely be casted to uint128\n        return ChainGas.wrap(uint128(GasData.unwrap(gasData_)) \u003c\u003c SHIFT_GAS_DATA | uint128(domain_));\n    }\n\n    /// @notice Wraps padded uint256 value into ChainGas struct.\n    function wrapChainGas(uint256 paddedChainGas) internal pure returns (ChainGas) {\n        // Casting to uint128 will truncate the highest bits, which is the behavior we want\n        return ChainGas.wrap(uint128(paddedChainGas));\n    }\n\n    /// @notice Returns the chain's gas data.\n    function gasData(ChainGas data) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(ChainGas.unwrap(data) \u003e\u003e SHIFT_GAS_DATA));\n    }\n\n    /// @notice Returns the chain's domain.\n    function domain(ChainGas data) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(ChainGas.unwrap(data));\n    }\n\n    /// @notice Returns the hash for the list of ChainGas structs.\n    function snapGasHash(ChainGas[] memory snapGas) internal pure returns (bytes32 snapGasHash_) {\n        // Use assembly to calculate the hash of the array without copying it\n        // ChainGas takes a single word of storage, thus ChainGas[] is stored in the following way:\n        // 0x00: length of the array, in words\n        // 0x20: first ChainGas struct\n        // 0x40: second ChainGas struct\n        // And so on...\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Find the location where the array data starts, we add 0x20 to skip the length field\n            let loc := add(snapGas, 0x20)\n            // Load the length of the array (in words).\n            // Shifting left 5 bits is equivalent to multiplying by 32: this converts from words to bytes.\n            let len := shl(5, mload(snapGas))\n            // Calculate the hash of the array\n            snapGasHash_ := keccak256(loc, len)\n        }\n    }\n}\n\n// contracts/libs/stack/Header.sol\n\n/// Header is encoded data with \"general routing information\".\ntype Header is uint136;\n\nusing HeaderLib for Header global;\n\n/// Types of messages supported by Origin-Destination\n/// - Base: message sent by protocol user, contains tips\n/// - Manager: message sent between AgentManager contracts located on different chains, no tips\nenum MessageFlag {\n    Base,\n    Manager\n}\n\nusing HeaderLib for MessageFlag global;\n\n/// Library for formatting _the header part_ of _the messages used by Origin and Destination_.\n/// - Header represents general information for routing a Message for Origin and Destination.\n/// - Header occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n///\n/// # Header stack layout (from highest bits to lowest)\n///\n/// | Position   | Field            | Type   | Bytes | Description                             |\n/// | ---------- | ---------------- | ------ | ----- | --------------------------------------- |\n/// | (017..016] | flag             | uint8  | 1     | Flag specifying the type of message     |\n/// | (016..012] | origin           | uint32 | 4     | Domain where message originated         |\n/// | (012..008] | nonce            | uint32 | 4     | Message nonce on the origin domain      |\n/// | (008..004] | destination      | uint32 | 4     | Domain where message will be executed   |\n/// | (004..000] | optimisticPeriod | uint32 | 4     | Optimistic period that will be enforced |\nlibrary HeaderLib {\n    /// @dev Amount of bits to shift to flag field\n    uint136 private constant SHIFT_FLAG = 16 * 8;\n    /// @dev Amount of bits to shift to origin field\n    uint136 private constant SHIFT_ORIGIN = 12 * 8;\n    /// @dev Amount of bits to shift to nonce field\n    uint136 private constant SHIFT_NONCE = 8 * 8;\n    /// @dev Amount of bits to shift to destination field\n    uint136 private constant SHIFT_DESTINATION = 4 * 8;\n\n    /// @notice Returns an encoded header with provided fields\n    /// @param origin_              Domain of origin chain\n    /// @param nonce_               Message nonce on origin chain\n    /// @param destination_         Domain of destination chain\n    /// @param optimisticPeriod_    Optimistic period for message execution\n    function encodeHeader(\n        MessageFlag flag_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint32 destination_,\n        uint32 optimisticPeriod_\n    ) internal pure returns (Header) {\n        // All casts below are upcasts, so they are safe\n        // forgefmt: disable-next-item\n        return Header.wrap(\n            uint136(uint8(flag_)) \u003c\u003c SHIFT_FLAG |\n            uint136(origin_) \u003c\u003c SHIFT_ORIGIN |\n            uint136(nonce_) \u003c\u003c SHIFT_NONCE |\n            uint136(destination_) \u003c\u003c SHIFT_DESTINATION |\n            uint136(optimisticPeriod_)\n        );\n    }\n\n    /// @notice Checks that the header is a valid encoded header.\n    function isHeader(uint256 paddedHeader) internal pure returns (bool) {\n        // Check that flag is within range\n        return _flag(paddedHeader) \u003c= uint8(type(MessageFlag).max);\n    }\n\n    /// @notice Wraps the padded encoded request into a Header-typed value.\n    /// @dev The \"padded\" header is simply an encoded header casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded headers\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedHeader) internal pure returns (Header) {\n        // Check that flag is within range\n        if (!isHeader(paddedHeader)) revert FlagOutOfRange();\n        // Casting to uint136 will truncate the highest bits, which is the behavior we want\n        return Header.wrap(uint136(paddedHeader));\n    }\n\n    /// @notice Returns header's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Header header) internal pure returns (bytes32 hashedHeader) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store header in scratch space\n            mstore(0, header)\n            // Compute hash of header padded to 32 bytes\n            hashedHeader := keccak256(0, 32)\n        }\n    }\n\n    // ══════════════════════════════════════════════ HEADER SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns header's flag field\n    function flag(Header header) internal pure returns (MessageFlag) {\n        // We check that flag is within range when wrapping the header, so this cast is safe\n        return MessageFlag(_flag(Header.unwrap(header)));\n    }\n\n    /// @notice Returns header's origin field\n    function origin(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_ORIGIN);\n    }\n\n    /// @notice Returns header's nonce field\n    function nonce(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_NONCE);\n    }\n\n    /// @notice Returns header's destination field\n    function destination(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_DESTINATION);\n    }\n\n    /// @notice Returns header's optimistic seconds field\n    function optimisticPeriod(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns header's flag field without casting to MessageFlag\n    function _flag(uint256 paddedHeader) private pure returns (uint8) {\n        // Casting to uint8 will truncate the highest bits, which is the behavior we want\n        return uint8(paddedHeader \u003e\u003e SHIFT_FLAG);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n     * constructor.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall \u0026\u0026 _initialized \u003c 1) || (!AddressUpgradeable.isContract(address(this)) \u0026\u0026 _initialized == 1),\n            \"Initializable: contract is already initialized\"\n        );\n        _initialized = 1;\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: setting the version to 255 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing \u0026\u0026 _initialized \u003c version, \"Initializable: contract is already initialized\");\n        _initialized = version;\n        _initializing = true;\n        _;\n        _initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        require(_initializing, \"Initializable: contract is not initializing\");\n        _;\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized != type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint8) {\n        return _initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _initializing;\n    }\n}\n\n// contracts/interfaces/IAgentManager.sol\n\ninterface IAgentManager {\n    /**\n     * @notice Allows Inbox to open a Dispute between a Guard and a Notary, if they are both not in Dispute already.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Guard or Notary is already in Dispute.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Allows Inbox to slash an agent, if their fraud was proven.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Domain doesn't match the saved agent domain.\n     * @param domain    Domain where the Agent is active\n     * @param agent     Address of the Agent\n     * @param prover    Address that initially provided fraud proof\n     */\n    function slashAgent(uint32 domain, address agent, address prover) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest known root of the Agent Merkle Tree.\n     */\n    function agentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns the number of opened Disputes.\n     * @dev This includes the Disputes that have been resolved already.\n     */\n    function getDisputesAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns information about the dispute with the given index.\n     * @dev Will revert if dispute with given index hasn't been opened yet.\n     * @param index             Dispute index\n     * @return guard            Address of the Guard in the Dispute\n     * @return notary           Address of the Notary in the Dispute\n     * @return slashedAgent     Address of the Agent who was slashed when Dispute was resolved\n     * @return fraudProver      Address who provided fraud proof to resolve the Dispute\n     * @return reportPayload    Raw payload with report data that led to the Dispute\n     * @return reportSignature  Guard signature for the report payload\n     */\n    function getDispute(uint256 index)\n        external\n        view\n        returns (\n            address guard,\n            address notary,\n            address slashedAgent,\n            address fraudProver,\n            bytes memory reportPayload,\n            bytes memory reportSignature\n        );\n\n    /**\n     * @notice Returns the current Dispute status of a given agent. See Structures.sol for details.\n     * @dev Every returned value will be set to zero if agent was not slashed and is not in Dispute.\n     * `rival` and `disputePtr` will be set to zero if the agent was slashed without being in Dispute.\n     * @param agent         Agent address\n     * @return flag         Flag describing the current Dispute status for the agent: None/Pending/Slashed\n     * @return rival        Address of the rival agent in the Dispute\n     * @return fraudProver  Address who provided fraud proof to resolve the Dispute\n     * @return disputePtr   Index of the opened Dispute PLUS ONE. Zero if agent is not in Dispute.\n     */\n    function disputeStatus(address agent)\n        external\n        view\n        returns (DisputeFlag flag, address rival, address fraudProver, uint256 disputePtr);\n}\n\n// contracts/interfaces/IAgentSecured.sol\n\ninterface IAgentSecured {\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * between a Guard and a Notary has been opened.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * has been resolved due to one of the agents being slashed.\n     * \u003e `rivalIndex` will be ZERO, if the slashed agent was not in the Dispute.\n     * @param slashedIndex  Index of the slashed agent in the Agent Merkle Tree\n     * @param rivalIndex    Index of the their Dispute Rival in the Agent Merkle Tree\n     */\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the address of the local AgentManager contract, which is treated as\n     * the \"source of truth\" for agent statuses.\n     */\n    function agentManager() external view returns (address);\n\n    /**\n     * @notice Returns the address of the local Inbox contract, which is treated as\n     * the \"source of truth\" for agent-signed statements.\n     * @dev Inbox passes verified agent statements to `IAgentSecured` contract.\n     */\n    function inbox() external view returns (address);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns (flag, openedAt, resolvedAt) that describes the latest status of\n     * the latest dispute for an agent with a given index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param agentIndex    Agent index in the Agent Merkle Tree\n     * @return              Latest dispute status for the given agent: (flag, openedAt, resolvedAt)\n     */\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory);\n}\n\n// contracts/libs/memory/ByteString.sol\n\n/// @dev CallData is a memory view over the payload to be used for an external call, i.e.\n/// recipient.call(callData). Its length is always (4 + 32 * N) bytes:\n/// - First 4 bytes represent the function selector.\n/// - 32 * N bytes represent N words that function arguments occupy.\ntype CallData is uint256;\n\n/// @dev Attach library functions to CallData\nusing ByteString for CallData global;\n\n/// @dev Signature is a memory view over a \"65 bytes\" array representing a ECDSA signature.\ntype Signature is uint256;\n\n/// @dev Attach library functions to Signature\nusing ByteString for Signature global;\n\nlibrary ByteString {\n    using MemViewLib for bytes;\n\n    /**\n     * @dev non-compact ECDSA signatures are enforced as of OZ 4.7.3\n     *\n     *      Signature payload memory layout\n     * [000 .. 032) r   bytes32 32 bytes\n     * [032 .. 064) s   bytes32 32 bytes\n     * [064 .. 065) v   uint8    1 byte\n     */\n    uint256 internal constant SIGNATURE_LENGTH = 65;\n    uint256 private constant OFFSET_R = 0;\n    uint256 private constant OFFSET_S = 32;\n    uint256 private constant OFFSET_V = 64;\n\n    /**\n     * @dev Calldata memory layout\n     * [000 .. 004) selector    bytes4  4 bytes\n     *      Optional: N function arguments\n     * [004 .. 036) arg1        bytes32 32 bytes\n     *      ..\n     * [AAA .. END) argN        bytes32 32 bytes\n     */\n    uint256 internal constant SELECTOR_LENGTH = 4;\n    uint256 private constant OFFSET_SELECTOR = 0;\n    uint256 private constant OFFSET_ARGUMENTS = SELECTOR_LENGTH;\n\n    // ═════════════════════════════════════════════════ SIGNATURE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the signature payload from the given values.\n     * @dev Using ByteString.formatSignature({r: r, s: s, v: v}) will make sure\n     * that params are given in the right order.\n     */\n    function formatSignature(bytes32 r, bytes32 s, uint8 v) internal pure returns (bytes memory) {\n        return abi.encodePacked(r, s, v);\n    }\n\n    /**\n     * @notice Returns a Signature view over for the given payload.\n     * @dev Will revert if the payload is not a signature.\n     */\n    function castToSignature(bytes memory payload) internal pure returns (Signature) {\n        return castToSignature(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Signature view.\n     * @dev Will revert if the memory view is not over a signature.\n     */\n    function castToSignature(MemView memView) internal pure returns (Signature) {\n        if (!isSignature(memView)) revert UnformattedSignature();\n        return Signature.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a signature\n     */\n    function isSignature(MemView memView) internal pure returns (bool) {\n        return memView.len() == SIGNATURE_LENGTH;\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Signature signature) internal pure returns (MemView) {\n        return MemView.wrap(Signature.unwrap(signature));\n    }\n\n    // ═════════════════════════════════════════════ SIGNATURE SLICING ═════════════════════════════════════════════════\n\n    /// @notice Unpacks signature payload into (r, s, v) parameters.\n    /// @dev Make sure to verify signature length with isSignature() beforehand.\n    function toRSV(Signature signature) internal pure returns (bytes32 r, bytes32 s, uint8 v) {\n        // Get the underlying memory view\n        MemView memView = unwrap(signature);\n        r = memView.index({index_: OFFSET_R, bytes_: 32});\n        s = memView.index({index_: OFFSET_S, bytes_: 32});\n        // Can be safely casted to uint8, since we index a single byte\n        v = uint8(memView.indexUint({index_: OFFSET_V, bytes_: 1}));\n    }\n\n    // ═════════════════════════════════════════════════ CALLDATA ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the calldata with the modified arguments:\n     * the existing arguments are prepended with the arguments from the prefix.\n     * @dev Given:\n     *  - `calldata = abi.encodeWithSelector(foo.selector, d, e);`\n     *  - `prefix = abi.encode(a, b, c);`\n     *  - `a`, `b`, `c` are arguments of static type (i.e. not dynamically sized ones)\n     *      Then:\n     *  - Function will return abi.encodeWithSelector(foo.selector, a, c, c, d, e)\n     *  - Returned calldata will trigger `foo(a, b, c, d, e)` when used for a contract call.\n     * Note: for clarification as to what types are considered static, see\n     * https://docs.soliditylang.org/en/latest/abi-spec.html#formal-specification-of-the-encoding\n     * @param callData  Calldata that needs to be modified\n     * @param prefix    ABI-encoded arguments to use as the first arguments in the new calldata\n     * @return Modified calldata having prefix as the first arguments.\n     */\n    function addPrefix(CallData callData, bytes memory prefix) internal view returns (bytes memory) {\n        // Prefix should occupy a whole amount of words in memory\n        if (!_fullWords(prefix.length)) revert UnformattedCallDataPrefix();\n        MemView[] memory views = new MemView[](3);\n        // Use payload's function selector\n        views[0] = abi.encodePacked(callData.callSelector()).ref();\n        // Use prefix as the first arguments\n        views[1] = prefix.ref();\n        // Use payload's remaining arguments\n        views[2] = callData.arguments();\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a CallData view over for the given payload.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(bytes memory payload) internal pure returns (CallData) {\n        return castToCallData(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a CallData view.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(MemView memView) internal pure returns (CallData) {\n        if (!isCallData(memView)) revert UnformattedCallData();\n        return CallData.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a valid calldata, i.e.\n     * a function selector, followed by arbitrary amount of arguments.\n     */\n    function isCallData(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Calldata should at least have a function selector\n        if (length \u003c SELECTOR_LENGTH) return false;\n        // The remainder of the calldata should be exactly N memory words (N \u003e= 0)\n        return _fullWords(length - SELECTOR_LENGTH);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(CallData callData) internal pure returns (MemView) {\n        return MemView.wrap(CallData.unwrap(callData));\n    }\n\n    /// @notice Returns callData's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(CallData callData) internal pure returns (bytes32) {\n        return callData.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ CALLDATA SLICING ══════════════════════════════════════════════════\n\n    /**\n     * @notice Returns amount of memory words (32 byte chunks) the function arguments\n     * occupy in the calldata.\n     * @dev This might differ from amount of arguments supplied, if any of the arguments\n     * occupies more than one memory slot. It is true, however, that argument part of the payload\n     * occupies exactly N words, even for dynamic types like `bytes`\n     */\n    function argumentWords(CallData callData) internal pure returns (uint256) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        // Equivalent of (length - SELECTOR_LENGTH) / 32\n        return (memView.len() - SELECTOR_LENGTH) \u003e\u003e 5;\n    }\n\n    /// @notice Returns selector for the provided calldata.\n    function callSelector(CallData callData) internal pure returns (bytes4) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return bytes4(memView.index({index_: OFFSET_SELECTOR, bytes_: SELECTOR_LENGTH}));\n    }\n\n    /// @notice Returns abi encoded arguments for the provided calldata.\n    function arguments(CallData callData) internal pure returns (MemView) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return memView.sliceFrom({index_: OFFSET_ARGUMENTS});\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if length is full amount of memory words (32 bytes).\n    function _fullWords(uint256 length) internal pure returns (bool) {\n        // The equivalent of length % 32 == 0\n        return length \u0026 31 == 0;\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n    function __Context_init() internal onlyInitializing {\n    }\n\n    function __Context_init_unchained() internal onlyInitializing {\n    }\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[50] private __gap;\n}\n\n// contracts/libs/merkle/MerkleTree.sol\n\n/// `BaseTree` is a struct representing incremental merkle tree.\n/// - Contains only the current branch.\n/// - The number of inserted leaves is stored externally, and is later supplied for tree operations.\n/// - Has a fixed height of `ORIGIN_TREE_HEIGHT`.\n/// - Can store up to `2 ** ORIGIN_TREE_HEIGHT - 1` leaves.\n/// \u003e Note: the hash function for the tree `H(x, y)` is defined as:\n/// \u003e - `H(0,0) = 0`\n/// \u003e - `H(x,y) = keccak256(x, y), when (x != 0 || y != 0)`\n/// ## Invariant for leafs\n/// - The leftmost empty leaf has `index == count`, where `count` is the amount of the inserted leafs so far.\n/// - Value for any empty leaf or node is bytes32(0).\n/// ## Invariant for current branch\n/// `branch[i]` is always the value of a node on the i-th level.\n/// Levels are numbered from leafs to root: `0 .. ORIGIN_TREE_HEIGHT`.\n/// `branch[i]` stores the value for the node, such that:\n//  - The node is a \"left child\" (e.g. has an even index).\n/// - The node must have two non-empty children.\n/// - Out of all level's \"left child\" nodes with \"non-empty children\",\n/// the one with the biggest index (the rightmost one) is stored as `branch[i]`.\n/// \u003e __`branch` could be used to form a proof of inclusion for the first empty leaf (`index == count`).__\n/// _Here is how:_\n/// - Let's walk along the path from the \"first empty leaf\" to the root.\n/// - i-th bit of the \"first empty leaf\" index (which is equal to `count`) determines if the path's node\n/// for this i-th level is a \"left child\" or a \"right child\".\n/// - i-th bit in `count` is 0 → we are the left child on this level → sibling is the right child\n/// that does not exist yet → `proof[i] = bytes32(0)`.\n/// - i-th bit in `count` is 1 → we are the right child on this level → sibling is the left child\n/// sibling is the rightmost \"left child\" node on the level → `proof[i] = branch[i]`.\n/// \u003e Therefore `proof[i] = (count \u0026 (1 \u003c\u003c i)) == 0 ? bytes32(0) : branch[i])`\nstruct BaseTree {\n    bytes32[ORIGIN_TREE_HEIGHT] branch;\n}\n\nusing MerkleTree for BaseTree global;\n\n/// `HistoricalTree` is an incremental merkle tree keeping track of its historical merkle roots.\n/// \u003e - `roots[N]` is the root of the tree after `N` leafs were inserted\n/// \u003e - `roots[0] == bytes32(0)`\n/// @param tree     Incremental merkle tree\n/// @param roots    Historical merkle roots of the tree\nstruct HistoricalTree {\n    BaseTree tree;\n    bytes32[] roots;\n}\n\nusing MerkleTree for HistoricalTree global;\n\n/// `DynamicTree` is a struct representing a Merkle Tree with `2**AGENT_TREE_HEIGHT` leaves.\n/// - A single operation is available: update value for leaf with an arbitrary index (which might be a non-empty leaf).\n/// - This is done by requesting the proof of inclusion for the old value, which is used to both\n/// verify the old value, and calculate the new root.\n/// \u003e Based on Original idea from [ER forum post](https://ethresear.ch/t/efficient-on-chain-dynamic-merkle-tree/11054).\nstruct DynamicTree {\n    bytes32 root;\n}\n\nusing MerkleTree for DynamicTree global;\n\n/// MerkleTree is work based on Nomad's Merkle.sol, which is used under MIT OR Apache-2.0\n/// [link](https://github.com/nomad-xyz/monorepo/blob/main/packages/contracts-core/contracts/libs/Merkle.sol).\n/// With the following changes:\n/// - Adapted for Solidity 0.8.x.\n/// - Amount of tree leaves stored externally.\n/// - Added thorough documentation.\n/// - `H(0,0) = 0` optimization from [ER forum post](https://ethresear.ch/t/optimizing-sparse-merkle-trees/3751/6).\n/// \u003e Nomad's Merkle.sol is work based on eth2 deposit contract, which is used under CC0-1.0\n///[link](https://github.com/ethereum/deposit_contract/blob/dev/deposit_contract/contracts/validator_registration.v.py).\n/// With the following changes:\n/// \u003e - Implemented in Solidity 0.7.6 (eth2 deposit contract implemented in Vyper).\n/// \u003e - `H() = keccak256()` is used as the hashing function instead of `sha256()`.\nlibrary MerkleTree {\n    /// @dev For root calculation we need at least one empty leaf, thus the minus one in the formula.\n    uint256 internal constant MAX_LEAVES = 2 ** ORIGIN_TREE_HEIGHT - 1;\n\n    // ═════════════════════════════════════════════════ BASE TREE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Inserts `node` into merkle tree\n     * @dev Reverts if tree is full\n     * @param newCount  Amount of inserted leaves in the tree after the insertion (i.e. current + 1)\n     * @param node      Element to insert into tree\n     */\n    function insertBase(BaseTree storage tree, uint256 newCount, bytes32 node) internal {\n        if (newCount \u003e MAX_LEAVES) revert MerkleTreeFull();\n        // We go up the tree following the branch from the empty leaf AFTER the just inserted one.\n        // We stop when we find the first \"right child\" node.\n        // Its sibling is now the rightmost \"left child\" node that has two non-empty children.\n        // Therefore we need to update `tree.branch` value on this level.\n        // One could see that `tree.branch` value on lower and higher levels remain unchanged.\n\n        // Loop invariant: `node` is the current level's value for the branch from JUST INSERTED leaf\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            if ((newCount \u0026 1) == 1) {\n                // Found the first \"right child\" node on the branch from EMPTY leaf\n                // `node` is the value for node on branch from JUST INSERTED leaf\n                // Which in this case is the \"left child\".\n                // We update tree.branch and exit\n                tree.branch[i] = node;\n                return;\n            }\n            // On the branch from EMPTY leaf this is still a \"left child\".\n            // Meaning on branch from JUST INSERTED leaf, `node` is a right child.\n            // We compute value for `node` parent using `tree.branch` invariant:\n            // This is the rightmost \"left child\" node, which would be sibling of `node`.\n            node = MerkleMath.getParent(tree.branch[i], node);\n            // Get the parent index, and go to the next tree level\n            newCount \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n        // As the loop should always end prematurely with the `return` statement,\n        // this code should be unreachable. We assert `false` just to be safe.\n        assert(false);\n    }\n\n    /**\n     * @notice Calculates and returns current root of the merkle tree.\n     * @param count     Current amount of inserted leaves in the tree\n     * @return current  Calculated root of `tree`\n     */\n    function rootBase(BaseTree storage tree, uint256 count) internal view returns (bytes32 current) {\n        // To calculate the root we follow the branch of first EMPTY leaf (index == count)\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            // Check if we are the left or the right child on the current level\n            if ((count \u0026 1) == 1) {\n                // We are the right child. Our sibling is the \"rightmost\" \"left-child\" node\n                // that has two non-empty children → sibling is `tree.branch[i]`\n                current = MerkleMath.getParent(tree.branch[i], current);\n            } else {\n                // We are the left child. Our sibling does not exist yet → sibling is EMPTY\n                current = MerkleMath.getParent(current, bytes32(0));\n            }\n            // Get the parent index, and go to the next tree level\n            count \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    // ══════════════════════════════════════════════ HISTORICAL TREE ══════════════════════════════════════════════════\n\n    /// @notice Initializes the historical roots for the tree by inserting an empty root.\n    // solhint-disable-next-line ordering\n    function initializeRoots(HistoricalTree storage tree) internal returns (bytes32 savedRoot) {\n        // This should only be called once, when the contract is initialized\n        assert(tree.roots.length == 0);\n        // Save root for empty merkle tree: bytes32(0)\n        tree.roots.push(savedRoot);\n    }\n\n    /// @notice Inserts a new leaf into the merkle tree.\n    /// @dev Reverts if tree is full.\n    /// @param node         Element to insert into tree\n    /// @return newRoot     Merkle root after the leaf was inserted\n    function insert(HistoricalTree storage tree, bytes32 node) internal returns (bytes32 newRoot) {\n        // Tree count after the new leaf will be inserted (we store roots[0] as root of empty tree)\n        uint256 newCount = tree.roots.length;\n        tree.tree.insertBase(newCount, node);\n        // Save the new root\n        newRoot = tree.tree.rootBase(newCount);\n        tree.roots.push(newRoot);\n    }\n\n    /// @notice Returns the historical root of the merkle tree.\n    /// @dev Reverts if not enough leafs have been inserted.\n    /// @param count            Amount of leafs in the tree at some point of time\n    /// @return historicalRoot  Merkle root after `count` leafs were inserted\n    function root(HistoricalTree storage tree, uint256 count) internal view returns (bytes32 historicalRoot) {\n        if (count \u003e= tree.roots.length) revert NotEnoughLeafs();\n        return tree.roots[count];\n    }\n\n    // ═══════════════════════════════════════════════ DYNAMIC TREE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Updates the value for the leaf with the given index in the Dynamic Merkle Tree.\n     * @dev Will revert if incorrect proof of inclusion for old value is supplied.\n     * @param tree          Dynamic merkle tree\n     * @param index         Index of the leaf to update\n     * @param oldValue      Previous value of the leaf\n     * @param branch        Proof of inclusion of previous value into the tree\n     * @param newValue      New leaf value to assign\n     * @return newRoot      New value for the Merkle Root after the leaf is updated\n     */\n    function update(\n        DynamicTree storage tree,\n        uint256 index,\n        bytes32 oldValue,\n        bytes32[] memory branch,\n        bytes32 newValue\n    ) internal returns (bytes32 newRoot) {\n        // Check that the old value + proof result in a correct root\n        if (MerkleMath.proofRoot(index, oldValue, branch, AGENT_TREE_HEIGHT) != tree.root) {\n            revert LeafNotProven();\n        }\n        // New root is new value + the same proof (values for sibling nodes are not updated)\n        newRoot = MerkleMath.proofRoot(index, newValue, branch, AGENT_TREE_HEIGHT);\n        // Write the new root\n        tree.root = newRoot;\n    }\n}\n\n// contracts/libs/stack/Tips.sol\n\n/// Tips is encoded data with \"tips paid for sending a base message\".\n/// Note: even though uint256 is also an underlying type for MemView, Tips is stored ON STACK.\ntype Tips is uint256;\n\nusing TipsLib for Tips global;\n\n/// # Tips\n/// Library for formatting _the tips part_ of _the base messages_.\n///\n/// ## How the tips are awarded\n/// Tips are paid for sending a base message, and are split across all the agents that\n/// made the message execution on destination chain possible.\n/// ### Summit tips\n/// Split between:\n///     - Guard posting a snapshot with state ST_G for the origin chain.\n///     - Notary posting a snapshot SN_N using ST_G. This creates attestation A.\n///     - Notary posting a message receipt after it is executed on destination chain.\n/// ### Attestation tips\n/// Paid to:\n///     - Notary posting attestation A to destination chain.\n/// ### Execution tips\n/// Paid to:\n///     - First executor performing a valid execution attempt (correct proofs, optimistic period over),\n///      using attestation A to prove message inclusion on origin chain, whether the recipient reverted or not.\n/// ### Delivery tips.\n/// Paid to:\n///     - Executor who successfully executed the message on destination chain.\n///\n/// ## Tips encoding\n/// - Tips occupy a single storage word, and thus are stored on stack instead of being stored in memory.\n/// - The actual tip values should be determined by multiplying stored values by divided by TIPS_MULTIPLIER=2**32.\n/// - Tips are packed into a single word of storage, while allowing real values up to ~8*10**28 for every tip category.\n/// \u003e The only downside is that the \"real tip values\" are now multiplies of ~4*10**9, which should be fine even for\n/// the chains with the most expensive gas currency.\n/// # Tips stack layout (from highest bits to lowest)\n///\n/// | Position   | Field          | Type   | Bytes | Description                                                |\n/// | ---------- | -------------- | ------ | ----- | ---------------------------------------------------------- |\n/// | (032..024] | summitTip      | uint64 | 8     | Tip for agents interacting with Summit contract            |\n/// | (024..016] | attestationTip | uint64 | 8     | Tip for Notary posting attestation to Destination contract |\n/// | (016..008] | executionTip   | uint64 | 8     | Tip for valid execution attempt on destination chain       |\n/// | (008..000] | deliveryTip    | uint64 | 8     | Tip for successful message delivery on destination chain   |\n\nlibrary TipsLib {\n    using SafeCast for uint256;\n\n    /// @dev Amount of bits to shift to summitTip field\n    uint256 private constant SHIFT_SUMMIT_TIP = 24 * 8;\n    /// @dev Amount of bits to shift to attestationTip field\n    uint256 private constant SHIFT_ATTESTATION_TIP = 16 * 8;\n    /// @dev Amount of bits to shift to executionTip field\n    uint256 private constant SHIFT_EXECUTION_TIP = 8 * 8;\n\n    // ═══════════════════════════════════════════════════ TIPS ════════════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips with the given fields\n    /// @param summitTip_        Tip for agents interacting with Summit contract, divided by TIPS_MULTIPLIER\n    /// @param attestationTip_   Tip for Notary posting attestation to Destination contract, divided by TIPS_MULTIPLIER\n    /// @param executionTip_     Tip for valid execution attempt on destination chain, divided by TIPS_MULTIPLIER\n    /// @param deliveryTip_      Tip for successful message delivery on destination chain, divided by TIPS_MULTIPLIER\n    function encodeTips(uint64 summitTip_, uint64 attestationTip_, uint64 executionTip_, uint64 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // forgefmt: disable-next-item\n        return Tips.wrap(\n            uint256(summitTip_) \u003c\u003c SHIFT_SUMMIT_TIP |\n            uint256(attestationTip_) \u003c\u003c SHIFT_ATTESTATION_TIP |\n            uint256(executionTip_) \u003c\u003c SHIFT_EXECUTION_TIP |\n            uint256(deliveryTip_)\n        );\n    }\n\n    /// @notice Convenience function to encode tips with uint256 values.\n    function encodeTips256(uint256 summitTip_, uint256 attestationTip_, uint256 executionTip_, uint256 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // In practice, the tips amounts are not supposed to be higher than 2**96, and with 32 bits of granularity\n        // using uint64 is enough to store the values. However, we still check for overflow just in case.\n        // TODO: consider using Number type to store the tips values.\n        return encodeTips({\n            summitTip_: (summitTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            attestationTip_: (attestationTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            executionTip_: (executionTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            deliveryTip_: (deliveryTip_ \u003e\u003e TIPS_GRANULARITY).toUint64()\n        });\n    }\n\n    /// @notice Wraps the padded encoded tips into a Tips-typed value.\n    /// @dev There is no actual padding here, as the underlying type is already uint256,\n    /// but we include this function for consistency and to be future-proof, if tips will eventually use anything\n    /// smaller than uint256.\n    function wrapPadded(uint256 paddedTips) internal pure returns (Tips) {\n        return Tips.wrap(paddedTips);\n    }\n\n    /**\n     * @notice Returns a formatted Tips payload specifying empty tips.\n     * @return Formatted tips\n     */\n    function emptyTips() internal pure returns (Tips) {\n        return Tips.wrap(0);\n    }\n\n    /// @notice Returns tips's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Tips tips) internal pure returns (bytes32 hashedTips) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store tips in scratch space\n            mstore(0, tips)\n            // Compute hash of tips padded to 32 bytes\n            hashedTips := keccak256(0, 32)\n        }\n    }\n\n    // ═══════════════════════════════════════════════ TIPS SLICING ════════════════════════════════════════════════════\n\n    /// @notice Returns summitTip field\n    function summitTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_SUMMIT_TIP);\n    }\n\n    /// @notice Returns attestationTip field\n    function attestationTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_ATTESTATION_TIP);\n    }\n\n    /// @notice Returns executionTip field\n    function executionTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_EXECUTION_TIP);\n    }\n\n    /// @notice Returns deliveryTip field\n    function deliveryTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips));\n    }\n\n    // ════════════════════════════════════════════════ TIPS VALUE ═════════════════════════════════════════════════════\n\n    /// @notice Returns total value of the tips payload.\n    /// This is the sum of the encoded values, scaled up by TIPS_MULTIPLIER\n    function value(Tips tips) internal pure returns (uint256 value_) {\n        value_ = uint256(tips.summitTip()) + tips.attestationTip() + tips.executionTip() + tips.deliveryTip();\n        value_ \u003c\u003c= TIPS_GRANULARITY;\n    }\n\n    /// @notice Increases the delivery tip to match the new value.\n    function matchValue(Tips tips, uint256 newValue) internal pure returns (Tips newTips) {\n        uint256 oldValue = tips.value();\n        if (newValue \u003c oldValue) revert TipsValueTooLow();\n        // We want to increase the delivery tip, while keeping the other tips the same\n        unchecked {\n            uint256 delta = (newValue - oldValue) \u003e\u003e TIPS_GRANULARITY;\n            // `delta` fits into uint224, as TIPS_GRANULARITY is 32, so this never overflows uint256.\n            // In practice, this will never overflow uint64 as well, but we still check it just in case.\n            if (delta + tips.deliveryTip() \u003e type(uint64).max) revert TipsOverflow();\n            // Delivery tips occupy lowest 8 bytes, so we can just add delta to the tips value\n            // to effectively increase the delivery tip (knowing that delta fits into uint64).\n            newTips = Tips.wrap(Tips.unwrap(tips) + delta);\n        }\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    function __Ownable_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable_init_unchained() internal onlyInitializing {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n    function __Ownable2Step_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable2Step_init_unchained() internal onlyInitializing {\n    }\n    address private _pendingOwner;\n\n    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Returns the address of the pending owner.\n     */\n    function pendingOwner() public view virtual returns (address) {\n        return _pendingOwner;\n    }\n\n    /**\n     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual override onlyOwner {\n        _pendingOwner = newOwner;\n        emit OwnershipTransferStarted(owner(), newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual override {\n        delete _pendingOwner;\n        super._transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev The new owner accepts the ownership transfer.\n     */\n    function acceptOwnership() public virtual {\n        address sender = _msgSender();\n        require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n        _transferOwnership(sender);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// contracts/libs/memory/State.sol\n\n/// State is a memory view over a formatted state payload.\ntype State is uint256;\n\nusing StateLib for State global;\n\n/// # State\n/// State structure represents the state of Origin contract at some point of time.\n/// - State is structured in a way to track the updates of the Origin Merkle Tree.\n/// - State includes root of the Origin Merkle Tree, origin domain and some additional metadata.\n/// ## Origin Merkle Tree\n/// Hash of every sent message is inserted in the Origin Merkle Tree, which changes\n/// the value of Origin Merkle Root (which is the root for the mentioned tree).\n/// - Origin has a single Merkle Tree for all messages, regardless of their destination domain.\n/// - This leads to Origin state being updated if and only if a message was sent in a block.\n/// - Origin contract is a \"source of truth\" for states: a state is considered \"valid\" in its Origin,\n/// if it matches the state of the Origin contract after the N-th (nonce) message was sent.\n///\n/// # Memory layout of State fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                    |\n/// | ---------- | ----------- | ------- | ----- | ------------------------------ |\n/// | [000..032) | root        | bytes32 | 32    | Root of the Origin Merkle Tree |\n/// | [032..036) | origin      | uint32  | 4     | Domain where Origin is located |\n/// | [036..040) | nonce       | uint32  | 4     | Amount of sent messages        |\n/// | [040..045) | blockNumber | uint40  | 5     | Block of last sent message     |\n/// | [045..050) | timestamp   | uint40  | 5     | Time of last sent message      |\n/// | [050..062) | gasData     | uint96  | 12    | Gas data for the chain         |\n///\n/// @dev State could be used to form a Snapshot to be signed by a Guard or a Notary.\nlibrary StateLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_ROOT = 0;\n    uint256 private constant OFFSET_ORIGIN = 32;\n    uint256 private constant OFFSET_NONCE = 36;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 40;\n    uint256 private constant OFFSET_TIMESTAMP = 45;\n    uint256 private constant OFFSET_GAS_DATA = 50;\n\n    // ═══════════════════════════════════════════════════ STATE ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted State payload with provided fields\n     * @param root_         New merkle root\n     * @param origin_       Domain of Origin's chain\n     * @param nonce_        Nonce of the merkle root\n     * @param blockNumber_  Block number when root was saved in Origin\n     * @param timestamp_    Block timestamp when root was saved in Origin\n     * @param gasData_      Gas data for the chain\n     * @return Formatted state\n     */\n    function formatState(\n        bytes32 root_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_,\n        GasData gasData_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(root_, origin_, nonce_, blockNumber_, timestamp_, gasData_);\n    }\n\n    /**\n     * @notice Returns a State view over the given payload.\n     * @dev Will revert if the payload is not a state.\n     */\n    function castToState(bytes memory payload) internal pure returns (State) {\n        return castToState(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a State view.\n     * @dev Will revert if the memory view is not over a state.\n     */\n    function castToState(MemView memView) internal pure returns (State) {\n        if (!isState(memView)) revert UnformattedState();\n        return State.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted State.\n    function isState(MemView memView) internal pure returns (bool) {\n        return memView.len() == STATE_LENGTH;\n    }\n\n    /// @notice Returns the hash of a State, that could be later signed by a Guard to signal\n    /// that the state is invalid.\n    function hashInvalid(State state) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(stateInvalidSalt, keccak(state))\n        return state.unwrap().keccakSalted(STATE_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(State state) internal pure returns (MemView) {\n        return MemView.wrap(State.unwrap(state));\n    }\n\n    /// @notice Compares two State structures.\n    function equals(State a, State b) internal pure returns (bool) {\n        // Length of a State payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═══════════════════════════════════════════════ STATE HASHING ═══════════════════════════════════════════════════\n\n    /// @notice Returns the hash of the State.\n    /// @dev We are using the Merkle Root of a tree with two leafs (see below) as state hash.\n    function leaf(State state) internal pure returns (bytes32) {\n        (bytes32 leftLeaf_, bytes32 rightLeaf_) = state.subLeafs();\n        // Final hash is the parent of these leafs\n        return keccak256(bytes.concat(leftLeaf_, rightLeaf_));\n    }\n\n    /// @notice Returns \"sub-leafs\" of the State. Hash of these \"sub leafs\" is going to be used\n    /// as a \"state leaf\" in the \"Snapshot Merkle Tree\".\n    /// This enables proving that leftLeaf = (root, origin) was a part of the \"Snapshot Merkle Tree\",\n    /// by combining `rightLeaf` with the remainder of the \"Snapshot Merkle Proof\".\n    function subLeafs(State state) internal pure returns (bytes32 leftLeaf_, bytes32 rightLeaf_) {\n        MemView memView = state.unwrap();\n        // Left leaf is (root, origin)\n        leftLeaf_ = memView.prefix({len_: OFFSET_NONCE}).keccak();\n        // Right leaf is (metadata), or (nonce, blockNumber, timestamp)\n        rightLeaf_ = memView.sliceFrom({index_: OFFSET_NONCE}).keccak();\n    }\n\n    /// @notice Returns the left \"sub-leaf\" of the State.\n    function leftLeaf(bytes32 root_, uint32 origin_) internal pure returns (bytes32) {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(root_, origin_));\n    }\n\n    /// @notice Returns the right \"sub-leaf\" of the State.\n    function rightLeaf(uint32 nonce_, uint40 blockNumber_, uint40 timestamp_, GasData gasData_)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(nonce_, blockNumber_, timestamp_, gasData_));\n    }\n\n    // ═══════════════════════════════════════════════ STATE SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns a historical Merkle root from the Origin contract.\n    function root(State state) internal pure returns (bytes32) {\n        return state.unwrap().index({index_: OFFSET_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns domain of chain where the Origin contract is deployed.\n    function origin(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns nonce of Origin contract at the time, when `root` was the Merkle root.\n    function nonce(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when `root` was saved in Origin.\n    function blockNumber(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when `root` was saved in Origin.\n    /// @dev This is the timestamp according to the origin chain.\n    function timestamp(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n\n    /// @notice Returns gas data for the chain.\n    function gasData(State state) internal pure returns (GasData) {\n        return GasDataLib.wrapGasData(state.unwrap().indexUint({index_: OFFSET_GAS_DATA, bytes_: GAS_DATA_LENGTH}));\n    }\n}\n\n// contracts/libs/memory/BaseMessage.sol\n\n/// BaseMessage is a memory view over the base message supported by Origin-Destination\ntype BaseMessage is uint256;\n\nusing BaseMessageLib for BaseMessage global;\n\n/// BaseMessage structure represents a base message sent via the Origin-Destination contracts.\n/// - It only contains data relevant to the base message, the rest of data is encoded in the message header.\n/// - `sender` and `recipient` for EVM chains are EVM addresses casted to bytes32, while preserving left-alignment.\n/// - `tips` and `request` parameters are specified by a message sender\n/// \u003e Origin will calculate minimum tips for given request and content length, and will reject messages with tips\n/// lower than that.\n///\n/// # Memory layout of BaseMessage fields\n///\n/// | Position   | Field     | Type    | Bytes | Description                            |\n/// | ---------- | --------- | ------- | ----- | -------------------------------------- |\n/// | [000..032) | tips      | uint256 | 32    | Encoded tips paid on origin chain      |\n/// | [032..064) | sender    | bytes32 | 32    | Sender address on origin chain         |\n/// | [064..096) | recipient | bytes32 | 32    | Recipient address on destination chain |\n/// | [096..116) | request   | uint160 | 20    | Encoded request for message execution  |\n/// | [104..AAA) | content   | bytes   | ??    | Content to be passed to recipient      |\nlibrary BaseMessageLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_TIPS = 0;\n    uint256 private constant OFFSET_SENDER = 32;\n    uint256 private constant OFFSET_RECIPIENT = 64;\n    uint256 private constant OFFSET_REQUEST = OFFSET_RECIPIENT + TIPS_LENGTH;\n    uint256 private constant OFFSET_CONTENT = OFFSET_REQUEST + REQUEST_LENGTH;\n\n    // ═══════════════════════════════════════════════ BASE MESSAGE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted BaseMessage payload with provided fields.\n     * @param tips_         Encoded tips information\n     * @param sender_       Sender address on origin chain\n     * @param recipient_    Recipient address on destination chain\n     * @param request_      Encoded request for message execution\n     * @param content_      Raw content to be passed to recipient on destination chain\n     * @return Formatted base message\n     */\n    function formatBaseMessage(Tips tips_, bytes32 sender_, bytes32 recipient_, Request request_, bytes memory content_)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return abi.encodePacked(tips_, sender_, recipient_, request_, content_);\n    }\n\n    /**\n     * @notice Returns a BaseMessage view over the given payload.\n     * @dev Will revert if the payload is not a base message.\n     */\n    function castToBaseMessage(bytes memory payload) internal pure returns (BaseMessage) {\n        return castToBaseMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a BaseMessage view.\n     * @dev Will revert if the memory view is not over a base message payload.\n     */\n    function castToBaseMessage(MemView memView) internal pure returns (BaseMessage) {\n        if (!isBaseMessage(memView)) revert UnformattedBaseMessage();\n        return BaseMessage.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted BaseMessage.\n    function isBaseMessage(MemView memView) internal pure returns (bool) {\n        // Check if sender, recipient, tips fields exist\n        return (memView.len() \u003e= OFFSET_CONTENT);\n        // Content could be empty, so we don't check that\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(BaseMessage baseMessage) internal pure returns (MemView) {\n        return MemView.wrap(BaseMessage.unwrap(baseMessage));\n    }\n\n    /// @notice Returns baseMessage's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        // We hash \"tips\" and \"everything but tips\" to make tips proofs easier to verify\n        return MerkleMath.getParent(baseMessage.tips().leaf(), baseMessage.bodyLeaf());\n    }\n\n    /// @notice Returns hash for the \"everything but tips\" part of the base message.\n    function bodyLeaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_SENDER}).keccak();\n    }\n\n    // ═══════════════════════════════════════════ BASE MESSAGE SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips paid on origin chain.\n    function tips(BaseMessage baseMessage) internal pure returns (Tips) {\n        return TipsLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_TIPS, bytes_: TIPS_LENGTH})));\n    }\n\n    /// @notice Returns sender address on origin chain.\n    function sender(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_SENDER, bytes_: 32});\n    }\n\n    /// @notice Returns recipient address on destination chain.\n    function recipient(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_RECIPIENT, bytes_: 32});\n    }\n\n    /// @notice Returns an encoded request for message execution on destination chain.\n    function request(BaseMessage baseMessage) internal pure returns (Request) {\n        return RequestLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_REQUEST, bytes_: REQUEST_LENGTH})));\n    }\n\n    /// @notice Returns an untyped memory view over the content to be passed to recipient.\n    function content(BaseMessage baseMessage) internal pure returns (MemView) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_CONTENT});\n    }\n}\n\n// contracts/base/MessagingBase.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for all messaging contracts.\n * - Provides context on the local chain's domain.\n * - Provides ownership functionality.\n * - Will be providing pausing functionality when it is implemented.\n */\nabstract contract MessagingBase is MultiCallable, Versioned, Ownable2StepUpgradeable {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @notice Domain of the local chain, set once upon contract creation\n    uint32 public immutable localDomain;\n    // @notice Domain of the Synapse chain, set once upon contract creation\n    uint32 public immutable synapseDomain;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev gap for upgrade safety\n    uint256[50] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    constructor(string memory version_, uint32 synapseDomain_) Versioned(version_) {\n        localDomain = ChainContext.chainId();\n        synapseDomain = synapseDomain_;\n    }\n\n    // TODO: Implement pausing\n\n    /**\n     * @dev Should be impossible to renounce ownership;\n     * we override OpenZeppelin OwnableUpgradeable's\n     * implementation of renounceOwnership to make it a no-op\n     */\n    function renounceOwnership() public override onlyOwner {} //solhint-disable-line no-empty-blocks\n}\n\n// contracts/libs/memory/Message.sol\n\n/// Message is a memory over over a formatted message payload.\ntype Message is uint256;\n\nusing MessageLib for Message global;\n\n/// Library for formatting the various messages supported by Origin and Destination.\n///\n/// # Message memory layout\n///\n/// | Position   | Field  | Type    | Bytes | Description                                             |\n/// | ---------- | ------ | ------- | ----- | ------------------------------------------------------- |\n/// | [000..017) | header | uint136 | 17    | Encoded general routing information for the message     |\n/// | [017..AAA) | body   | bytes   | ??    | Formatted payload (according to flag) with message body |\nlibrary MessageLib {\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MemViewLib for bytes;\n    using HeaderLib for MemView;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_HEADER = 0;\n    uint256 private constant OFFSET_BODY = OFFSET_HEADER + HEADER_LENGTH;\n\n    // ══════════════════════════════════════════════════ MESSAGE ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns formatted message with provided fields.\n     * @param header_   Encoded general routing information for the message\n     * @param body_     Formatted payload (according to flag) with message body\n     * @return Formatted message\n     */\n    function formatMessage(Header header_, bytes memory body_) internal pure returns (bytes memory) {\n        return abi.encodePacked(header_, body_);\n    }\n\n    /**\n     * @notice Returns a Message view over for the given payload.\n     * @dev Will revert if the payload is not a message payload.\n     */\n    function castToMessage(bytes memory payload) internal pure returns (Message) {\n        return castToMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Message view.\n     * @dev Will revert if the memory view is not over a message payload.\n     */\n    function castToMessage(MemView memView) internal pure returns (Message) {\n        if (!isMessage(memView)) revert UnformattedMessage();\n        return Message.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Message.\n     */\n    function isMessage(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Check if headers exist in the payload\n        if (length \u003c OFFSET_BODY) return false;\n        // Check that Header is valid\n        uint256 paddedHeader = _header(memView);\n        if (!HeaderLib.isHeader(paddedHeader)) return false;\n        // Check that body is formatted according to the flag\n        // Only Base/Manager message flags exist\n        if (HeaderLib.wrapPadded(paddedHeader).flag() == MessageFlag.Base) {\n            // Check if body is a formatted base message\n            return _body(memView).isBaseMessage();\n        } else {\n            // Check if body is a formatted calldata for AgentManager call\n            return _body(memView).isCallData();\n        }\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Message message) internal pure returns (MemView) {\n        return MemView.wrap(Message.unwrap(message));\n    }\n\n    /// @notice Returns message's hash: a leaf to be inserted in the Merkle tree.\n    function leaf(Message message) internal pure returns (bytes32) {\n        // We hash header and body separately to make message proofs easier to verify\n        Header header_ = message.header();\n        // Only Base/Manager message flags exist\n        if (header_.flag() == MessageFlag.Base) {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToBaseMessage().leaf());\n        } else {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToCallData().leaf());\n        }\n    }\n\n    // ══════════════════════════════════════════════ MESSAGE SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns message's encoded header field.\n    function header(Message message) internal pure returns (Header) {\n        return HeaderLib.wrapPadded((message.unwrap().indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH})));\n    }\n\n    /// @notice Returns message's body field as an untyped memory view.\n    function body(Message message) internal pure returns (MemView) {\n        MemView memView = message.unwrap();\n        return _body(memView);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns message's padded header without checking that it is a valid header.\n    function _header(MemView memView) private pure returns (uint256) {\n        return memView.indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH});\n    }\n\n    /// @dev Returns an untyped memory view over the body field without checking\n    /// if the whole payload or the body are properly formatted.\n    function _body(MemView memView) private pure returns (MemView) {\n        return memView.sliceFrom({index_: OFFSET_BODY});\n    }\n}\n\n// contracts/base/AgentSecured.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for messaging contracts that are secured by the agent manager.\n * `AgentSecured` relies on `AgentManager` to provide the following functionality:\n * - Keep track of agents and their statuses.\n * - Pass agent-signed statements that were verified by the agent manager.\n * - These statements are considered valid indefinitely, unless the agent is disputed.\n * - Disputes are opened and resolved by the agent manager.\n * \u003e `AgentSecured` implementation should never use statements signed by agents that are disputed.\n */\nabstract contract AgentSecured is MessagingBase, IAgentSecured {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    address public immutable agentManager;\n\n    /// @inheritdoc IAgentSecured\n    address public immutable inbox;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    // (agent index =\u003e their dispute status: flag, openedAt, resolvedAt)\n    mapping(uint32 =\u003e DisputeStatus) internal _disputes;\n\n    /// @dev gap for upgrade safety\n    uint256[49] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    modifier onlyAgentManager() {\n        if (msg.sender != agentManager) revert CallerNotAgentManager();\n        _;\n    }\n\n    modifier onlyInbox() {\n        if (msg.sender != inbox) revert CallerNotInbox();\n        _;\n    }\n\n    constructor(string memory version_, uint32 synapseDomain_, address agentManager_, address inbox_)\n        MessagingBase(version_, synapseDomain_)\n    {\n        agentManager = agentManager_;\n        inbox = inbox_;\n    }\n\n    // ════════════════════════════════════════════ ONLY AGENT MANAGER ═════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external onlyAgentManager {\n        uint40 openedAt = ChainContext.blockTimestamp();\n        DisputeStatus memory status = DisputeStatus({flag: DisputeFlag.Pending, openedAt: openedAt, resolvedAt: 0});\n        _disputes[guardIndex] = status;\n        _disputes[notaryIndex] = status;\n    }\n\n    /// @inheritdoc IAgentSecured\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external onlyAgentManager {\n        // Update the dispute status of the slashed agent first.\n        uint40 resolvedAt = ChainContext.blockTimestamp();\n        _disputes[slashedIndex].flag = DisputeFlag.Slashed;\n        _disputes[slashedIndex].resolvedAt = resolvedAt;\n        // Mark the rival agent as not disputed, if there was an ongoing dispute.\n        if (rivalIndex != 0) {\n            _disputes[rivalIndex].flag = DisputeFlag.None;\n            _disputes[rivalIndex].resolvedAt = resolvedAt;\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function agentStatus(address agent) external view returns (AgentStatus memory) {\n        return _agentStatus(agent);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status) {\n        return _getAgent(index);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory) {\n        return _disputes[agentIndex];\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns status of the given agent: (flag, domain, index).\n    function _agentStatus(address agent) internal view returns (AgentStatus memory) {\n        return IAgentManager(agentManager).agentStatus(agent);\n    }\n\n    /// @dev Returns agent and their status for a given agent index. Returns zero values for non existing indexes.\n    function _getAgent(uint256 index) internal view returns (address agent, AgentStatus memory status) {\n        return IAgentManager(agentManager).getAgent(index);\n    }\n\n    /// @dev Checks if a Dispute exists for the given Notary. This function returns true, if\n    /// Notary is in ongoing Dispute, or if Dispute was resolved not in Notary's favor.\n    /// In both cases we can't trust Notary's data.\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeExists(uint32 notaryIndex) internal view returns (bool) {\n        return _disputes[notaryIndex].flag != DisputeFlag.None;\n    }\n\n    /// @dev Checks if a Notary recently won a Dispute and is still in the \"post-dispute\" timeout period.\n    /// In this period we still can't trust Notary's data, though we can optimistically assume that\n    /// that the data will be correct after the timeout (assuming no new Disputes are opened).\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeTimeout(uint32 notaryIndex) internal view returns (bool) {\n        DisputeStatus memory status = _disputes[notaryIndex];\n        // Exit early if Notary is in ongoing Dispute / slashed.\n        if (status.flag != DisputeFlag.None) return false;\n        // Check if Notary has been in any Dispute at all.\n        if (status.openedAt == 0) return false;\n        // Otherwise check if the Dispute timeout is still active.\n        return block.timestamp \u003c status.resolvedAt + DISPUTE_TIMEOUT_NOTARY;\n    }\n}\n\n// contracts/hubs/StateHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StateHub` is a parent contract for `Origin`. It is responsible for the following:\n/// - Keeping track of the historical Origin Merkle Tree containing all the message hashes.\n/// - Keeping track of the historical Origin States, as well as verifying their validity.\nabstract contract StateHub is AgentSecured, StateHubEvents, IStateHub {\n    using SafeCast for uint256;\n    using StateLib for bytes;\n\n    struct OriginState {\n        uint40 blockNumber;\n        uint40 timestamp;\n        GasData gasData;\n    }\n    // Bits left for tight packing: 80\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Historical Merkle Tree\n    /// Note: Takes two storage slots\n    HistoricalTree private _tree;\n\n    /// @dev All historical contract States\n    OriginState[] private _originStates;\n\n    /// @dev gap for upgrade safety\n    uint256[47] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IStateHub\n    function isValidState(bytes memory statePayload) external view returns (bool isValid) {\n        // This will revert if payload is not a formatted state\n        State state = statePayload.castToState();\n        return _isValidState(state);\n    }\n\n    /// @inheritdoc IStateHub\n    function statesAmount() external view returns (uint256) {\n        return _originStates.length;\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestLatestState() external view returns (bytes memory stateData) {\n        // This never underflows, assuming the contract was initialized\n        return suggestState(_nextNonce() - 1);\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestState(uint32 nonce) public view returns (bytes memory stateData) {\n        // This will revert if nonce is out of range\n        bytes32 root = _tree.root(nonce);\n        return _formatOriginState(_originStates[nonce], root, localDomain, nonce);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Initializes the saved states list by inserting a state for an empty Merkle Tree.\n    function _initializeStates() internal {\n        // This should only be called once, when the contract is initialized\n        // This will revert if _tree.roots is non-empty\n        bytes32 savedRoot = _tree.initializeRoots();\n        // Save root for empty merkle _tree with block number and timestamp of initialization\n        _saveState(savedRoot, _toOriginState());\n    }\n\n    /// @dev Inserts leaf into the Merkle Tree and saves the updated origin State.\n    function _insertAndSave(bytes32 leaf) internal {\n        bytes32 newRoot = _tree.insert(leaf);\n        _saveState(newRoot, _toOriginState());\n    }\n\n    /// @dev Saves an updated state of the Origin contract\n    function _saveState(bytes32 root, OriginState memory state) internal {\n        uint32 nonce = _nextNonce();\n        _originStates.push(state);\n        // Emit event with raw state data\n        emit StateSaved(_formatOriginState(state, root, localDomain, nonce));\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns nonce of the next sent message: the amount of saved States so far.\n    /// This always equals to \"total amount of sent messages\" plus 1.\n    function _nextNonce() internal view returns (uint32) {\n        // TODO: consider using more than 32 bits for origin nonces\n        return _originStates.length.toUint32();\n    }\n\n    /// @dev Checks if a state is valid, i.e. if it matches the historical one.\n    /// Reverts, if state refers to another Origin contract.\n    function _isValidState(State state) internal view returns (bool) {\n        // Check if state refers to this contract\n        if (state.origin() != localDomain) revert IncorrectOriginDomain();\n        // Check if nonce exists\n        uint32 nonce = state.nonce();\n        if (nonce \u003e= _originStates.length) return false;\n        // Check if state root matches the historical one\n        if (state.root() != _tree.root(nonce)) return false;\n        // Check if state metadata matches the historical one\n        return _areEqual(state, _originStates[nonce]);\n    }\n\n    // ═════════════════════════════════════════════ STRUCT FORMATTING ═════════════════════════════════════════════════\n\n    /// @dev Returns a formatted payload for a stored OriginState.\n    function _formatOriginState(OriginState memory originState, bytes32 root, uint32 origin, uint32 nonce)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return StateLib.formatState({\n            root_: root,\n            origin_: origin,\n            nonce_: nonce,\n            blockNumber_: originState.blockNumber,\n            timestamp_: originState.timestamp,\n            gasData_: originState.gasData\n        });\n    }\n\n    /// @dev Child contract should implement the logic for getting the current gas data from the gas oracle\n    /// to be saved as part of the Origin State.\n    // solhint-disable-next-line ordering\n    function _fetchGasData() internal view virtual returns (GasData);\n\n    /// @dev Returns a OriginState struct to save in the contract.\n    function _toOriginState() internal view returns (OriginState memory originState) {\n        originState.blockNumber = ChainContext.blockNumber();\n        originState.timestamp = ChainContext.blockTimestamp();\n        originState.gasData = _fetchGasData();\n    }\n\n    /// @dev Checks that a state and its Origin representation are equal.\n    function _areEqual(State state, OriginState memory originState) internal pure returns (bool) {\n        return state.blockNumber() == originState.blockNumber \u0026\u0026 state.timestamp() == originState.timestamp;\n    }\n}\n\n// contracts/Origin.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Origin` contract is used for sending messages to remote chains. It is done\n/// by inserting the message hashes into the Origin Merkle, which makes it possible to\n/// prove that message was sent using the Merkle proof against the Origin Merkle Root. This essentially\n/// compresses the list of messages into a single 32-byte value that needs to be stored on the destination chain.\n/// `Origin` is responsible for the following:\n/// - Formatting the sent message payloads, and inserting their hashes into the Origin Merkle Tree.\n/// - Keeping track of its own historical states (see parent contract `StateHub`).\n/// - Enforcing minimum tip values for sent base messages based on the provided execution requests.\n/// - Distributing the collected tips upon request from a local `AgentManager` contract.\ncontract Origin is StateHub, OriginEvents, InterfaceOrigin {\n    using MemViewLib for bytes;\n    using MessageLib for bytes;\n    using TipsLib for bytes;\n    using TypeCasts for address;\n\n    address public immutable gasOracle;\n\n    modifier onlyRemoteDestination(uint32 destination) {\n        if (destination == localDomain) revert IncorrectDestinationDomain();\n        _;\n    }\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_, address gasOracle_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {\n        gasOracle = gasOracle_;\n    }\n\n    /// @notice Initializes Origin contract:\n    /// - msg.sender is set as contract owner\n    /// - State of \"empty merkle tree\" is saved\n    function initialize() external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize \"states\": state of an \"empty merkle tree\" is saved\n        _initializeStates();\n    }\n\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable onlyRemoteDestination(destination) returns (uint32 messageNonce, bytes32 messageHash) {\n        // Check that content is not too large\n        if (content.length \u003e MAX_CONTENT_BYTES) revert ContentLengthTooBig();\n        // This will revert if msg.value is lower than value of minimum tips\n        Tips tips = _getMinimumTips(destination, paddedRequest, content.length).matchValue(msg.value);\n        Request request = RequestLib.wrapPadded(paddedRequest);\n        // Format the BaseMessage body\n        bytes memory body = BaseMessageLib.formatBaseMessage({\n            sender_: msg.sender.addressToBytes32(),\n            recipient_: recipient,\n            tips_: tips,\n            request_: request,\n            content_: content\n        });\n        // Send the message\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Base, body);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        onlyAgentManager\n        onlyRemoteDestination(destination)\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // AgentManager (checked via modifier) is responsible for constructing the calldata payload correctly.\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Manager, payload);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function withdrawTips(address recipient, uint256 amount) external onlyAgentManager {\n        if (address(this).balance \u003c amount) revert InsufficientEthBalance();\n        (bool success,) = recipient.call{value: amount}(\"\");\n        if (!success) revert EthTransferFailed();\n        emit TipWithdrawalCompleted(recipient, amount);\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue)\n    {\n        return _getMinimumTips(destination, paddedRequest, contentLength).value();\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Sends the given message to the specified destination. Message hash is inserted\n    /// into the Origin Merkle Tree, which will enable message execution on destination chain.\n    function _sendMessage(uint32 destination, uint32 optimisticPeriod, MessageFlag flag, bytes memory body)\n        internal\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // Format the message header\n        messageNonce = _nextNonce();\n        Header header = flag.encodeHeader({\n            origin_: localDomain,\n            nonce_: messageNonce,\n            destination_: destination,\n            optimisticPeriod_: optimisticPeriod\n        });\n        // Format the full message payload\n        bytes memory msgPayload = MessageLib.formatMessage(header, body);\n        // Insert new leaf into the Origin Merkle Tree and save the updated state\n        messageHash = msgPayload.castToMessage().leaf();\n        _insertAndSave(messageHash);\n        // Emit event with message information\n        emit Sent(messageHash, messageNonce, destination, msgPayload);\n        // Update the gas oracle data. We do this after the provided tips are checked so that\n        // the provided message is sent in the event that the gas oracle data is updated to a higher value.\n        InterfaceGasOracle(gasOracle).updateGasData(destination);\n        // TODO: consider doing this before the message is sent, while adjusting GasOracle.getMinimumTips() to\n        // use the pending gas oracle data.\n    }\n\n    /// @dev Returns the minimum tips for sending a message to the given destination with the given request and content.\n    function _getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        internal\n        view\n        returns (Tips)\n    {\n        return\n            TipsLib.wrapPadded(InterfaceGasOracle(gasOracle).getMinimumTips(destination, paddedRequest, contentLength));\n    }\n\n    /// @dev Gets the current gas data from the gas oracle to be saved as part of the Origin State.\n    function _fetchGasData() internal view override returns (GasData) {\n        return GasDataLib.wrapGasData(InterfaceGasOracle(gasOracle).getGasData());\n    }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"181977:7325:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;181977:7325:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"181977:7325:0:-:0;;;;;;;;","abiDefinition":[],"userDoc":{"kind":"user","methods":{},"notice":"# State State structure represents the state of Origin contract at some point of time. - State is structured in a way to track the updates of the Origin Merkle Tree. - State includes root of the Origin Merkle Tree, origin domain and some additional metadata. ## Origin Merkle Tree Hash of every sent message is inserted in the Origin Merkle Tree, which changes the value of Origin Merkle Root (which is the root for the mentioned tree). - Origin has a single Merkle Tree for all messages, regardless of their destination domain. - This leads to Origin state being updated if and only if a message was sent in a block. - Origin contract is a \"source of truth\" for states: a state is considered \"valid\" in its Origin, if it matches the state of the Origin contract after the N-th (nonce) message was sent. # Memory layout of State fields | Position   | Field       | Type    | Bytes | Description                    | | ---------- | ----------- | ------- | ----- | ------------------------------ | | [000..032) | root        | bytes32 | 32    | Root of the Origin Merkle Tree | | [032..036) | origin      | uint32  | 4     | Domain where Origin is located | | [036..040) | nonce       | uint32  | 4     | Amount of sent messages        | | [040..045) | blockNumber | uint40  | 5     | Block of last sent message     | | [045..050) | timestamp   | uint40  | 5     | Time of last sent message      | | [050..062) | gasData     | uint96  | 12    | Gas data for the chain         |","version":1},"developerDoc":{"details":"State could be used to form a Snapshot to be signed by a Guard or a Notary.","kind":"dev","methods":{},"stateVariables":{"OFFSET_ROOT":{"details":"The variables below are not supposed to be used outside of the library directly."}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"details\":\"State could be used to form a Snapshot to be signed by a Guard or a Notary.\",\"kind\":\"dev\",\"methods\":{},\"stateVariables\":{\"OFFSET_ROOT\":{\"details\":\"The variables below are not supposed to be used outside of the library directly.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"# State State structure represents the state of Origin contract at some point of time. - State is structured in a way to track the updates of the Origin Merkle Tree. - State includes root of the Origin Merkle Tree, origin domain and some additional metadata. ## Origin Merkle Tree Hash of every sent message is inserted in the Origin Merkle Tree, which changes the value of Origin Merkle Root (which is the root for the mentioned tree). - Origin has a single Merkle Tree for all messages, regardless of their destination domain. - This leads to Origin state being updated if and only if a message was sent in a block. - Origin contract is a \\\"source of truth\\\" for states: a state is considered \\\"valid\\\" in its Origin, if it matches the state of the Origin contract after the N-th (nonce) message was sent. # Memory layout of State fields | Position   | Field       | Type    | Bytes | Description                    | | ---------- | ----------- | ------- | ----- | ------------------------------ | | [000..032) | root        | bytes32 | 32    | Root of the Origin Merkle Tree | | [032..036) | origin      | uint32  | 4     | Domain where Origin is located | | [036..040) | nonce       | uint32  | 4     | Amount of sent messages        | | [040..045) | blockNumber | uint40  | 5     | Block of last sent message     | | [045..050) | timestamp   | uint40  | 5     | Time of last sent message      | | [050..062) | gasData     | uint96  | 12    | Gas data for the chain         |\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Origin.sol\":\"StateLib\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Origin.sol\":{\"keccak256\":\"0x96775924f147f3d1f8df8cdf56731fe52a15af8d8e12e608efb8158c112b18cd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e642a27f5fab3c62b4c02e9754e9e42b1cf2e5381dbea9d3d106d23b7772ebe6\",\"dweb:/ipfs/QmUwn7ZyBvPkjnMuK8ZMSexBUdNQnVtxwyoAyT4DXLQjra\"]}},\"version\":1}"},"hashes":{}},"solidity/Origin.sol:StructureUtils":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220fd50c0ba2048440e99cec4ac9afdc7bdf56db413e4fd525d596cab21dddcc84764736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220fd50c0ba2048440e99cec4ac9afdc7bdf56db413e4fd525d596cab21dddcc84764736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/OriginEvents.sol\n\n/// @notice A collection of events emitted by the Origin contract\nabstract contract OriginEvents {\n    /**\n     * @notice Emitted when a new message is sent.\n     * @param messageHash   Hash of message; the leaf inserted to the Merkle tree for the message\n     * @param nonce         Nonce of sent message (starts from 1)\n     * @param destination   Destination domain\n     * @param message       Raw bytes of message\n     */\n    event Sent(bytes32 indexed messageHash, uint32 indexed nonce, uint32 indexed destination, bytes message);\n\n    /**\n     * @notice Emitted when a tip withdrawal is completed.\n     * @param actor     Actor address\n     * @param tip       Tip value, denominated in local domain's wei\n     */\n    event TipWithdrawalCompleted(address actor, uint256 tip);\n}\n\n// contracts/events/StateHubEvents.sol\n\n/// @notice A collection of events emitted by the StateHub contract\nabstract contract StateHubEvents {\n    /**\n     * @notice Emitted when a new Origin State is saved after a message was sent.\n     * @param state     Raw payload with state data\n     */\n    event StateSaved(bytes state);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n    /**\n     * @notice Check that a given state is valid: matches the historical state of Origin contract.\n     * Note: any Agent including an invalid state in their snapshot will be slashed\n     * upon providing the snapshot and agent signature for it to Origin contract.\n     * @dev Will revert if any of these is true:\n     *  - State payload is not properly formatted.\n     * @param statePayload      Raw payload with state data\n     * @return isValid          Whether the provided state is valid\n     */\n    function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns the amount of saved states so far.\n     * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n     */\n    function statesAmount() external view returns (uint256);\n\n    /**\n     * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @return statePayload     Raw payload with the latest state data\n     */\n    function suggestLatestState() external view returns (bytes memory statePayload);\n\n    /**\n     * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @param nonce             Historical nonce to form a state\n     * @return statePayload     Raw payload with historical state data\n     */\n    function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/InterfaceGasOracle.sol\n\ninterface InterfaceGasOracle {\n    /**\n     * @notice Fetches the latest gas data for the chain from `Destination` contract,\n     * and uses it to update the oracle values for the requested chain.\n     * @param domain    Domain to update the gas data for\n     */\n    function updateGasData(uint32 domain) external;\n\n    /**\n     * @notice Returns the gas data for the local chain.\n     */\n    function getGasData() external view returns (uint256 paddedGasData);\n\n    /**\n     * @notice Returns the gas data for the given domain, in the decoded format.\n     * @param domain        Domain of chain to get gas data for\n     * @return gasPrice     Gas price for the chain (in Wei per gas unit)\n     * @return dataPrice    Calldata price (in Wei per byte of content)\n     * @return execBuffer   Tx fee safety buffer for message execution (in Wei)\n     * @return amortAttCost Amortized cost for attestation submission (in Wei)\n     * @return etherPrice   Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n     * @return markup       Markup for the message execution (in BWAD)\n     */\n    function getDecodedGasData(uint32 domain)\n        external\n        view\n        returns (\n            uint256 gasPrice,\n            uint256 dataPrice,\n            uint256 execBuffer,\n            uint256 amortAttCost,\n            uint256 etherPrice,\n            uint256 markup\n        );\n\n    /**\n     * @notice Returns the minimum tips for sending a message to a given destination.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return paddedTips       Padded encoded minimum tips information\n     */\n    function getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 paddedTips);\n}\n\n// contracts/interfaces/InterfaceOrigin.sol\n\ninterface InterfaceOrigin {\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /**\n     * @notice Send a message to the recipient located on destination domain.\n     * @dev Recipient has to conform to IMessageRecipient interface, otherwise message won't be delivered.\n     * Will revert if any of these is true:\n     * - `destination` is equal to contract's local domain\n     * - `content` length is greater than `MAX_CONTENT_BYTES`\n     * - `msg.value` is lower than value of minimum tips for the given message\n     * @param destination           Domain of destination chain\n     * @param recipient             Address of recipient on destination chain as bytes32\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param paddedRequest         Padded encoded message execution request on destination chain\n     * @param content               Raw bytes content of message\n     * @return messageNonce         Nonce of the sent message\n     * @return messageHash          Hash of the sent message\n     */\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable returns (uint32 messageNonce, bytes32 messageHash);\n\n    /**\n     * @notice Send a manager message to the destination domain.\n     * @dev This could only be called by AgentManager, which takes care of encoding the calldata payload.\n     * Note: (msgOrigin, proofMaturity) security args will be added to payload on the destination chain\n     * so that the AgentManager could verify where the Manager Message came from and how mature is the proof.\n     * Note: function is not payable, as no tips are required for sending a manager message.\n     * Will revert if `destination` is equal to contract's local domain.\n     * @param destination           Domain of destination chain\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param payload               Payload for calling AgentManager on destination chain (with extra security args)\n     */\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        returns (uint32 messageNonce, bytes32 messageHash);\n\n    // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Withdraws locked base message tips to the recipient.\n     * @dev Could only be called by a local AgentManager.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function withdrawTips(address recipient, uint256 amount) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the minimum tips value for sending a message to a given destination.\n     * @dev Using at least `tipsValue` as `msg.value` for `sendBaseMessage()`\n     * will guarantee that the message will be accepted.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return tipsValue        Minimum tips value for a message to be accepted\n     */\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue);\n}\n\n// contracts/libs/Constants.sol\n\n// Here we define common constants to enable their easier reusing later.\n\n// ══════════════════════════════════ MERKLE ═══════════════════════════════════\n/// @dev Height of the Agent Merkle Tree\nuint256 constant AGENT_TREE_HEIGHT = 32;\n/// @dev Height of the Origin Merkle Tree\nuint256 constant ORIGIN_TREE_HEIGHT = 32;\n/// @dev Height of the Snapshot Merkle Tree. Allows up to 64 leafs, e.g. up to 32 states\nuint256 constant SNAPSHOT_TREE_HEIGHT = 6;\n// ══════════════════════════════════ STRUCTS ══════════════════════════════════\n/// @dev See Attestation.sol: (bytes32,bytes32,uint32,uint40,uint40): 32+32+4+5+5\nuint256 constant ATTESTATION_LENGTH = 78;\n/// @dev See GasData.sol: (uint16,uint16,uint16,uint16,uint16,uint16): 2+2+2+2+2+2\nuint256 constant GAS_DATA_LENGTH = 12;\n/// @dev See Receipt.sol: (uint32,uint32,bytes32,bytes32,uint8,address,address,address): 4+4+32+32+1+20+20+20\nuint256 constant RECEIPT_LENGTH = 133;\n/// @dev See State.sol: (bytes32,uint32,uint32,uint40,uint40,GasData): 32+4+4+5+5+len(GasData)\nuint256 constant STATE_LENGTH = 50 + GAS_DATA_LENGTH;\n/// @dev Maximum amount of states in a single snapshot. Each state produces two leafs in the tree\nuint256 constant SNAPSHOT_MAX_STATES = 1 \u003c\u003c (SNAPSHOT_TREE_HEIGHT - 1);\n// ══════════════════════════════════ MESSAGE ══════════════════════════════════\n/// @dev See Header.sol: (uint8,uint32,uint32,uint32,uint32): 1+4+4+4+4\nuint256 constant HEADER_LENGTH = 17;\n/// @dev See Request.sol: (uint96,uint64,uint32): 12+8+4\nuint256 constant REQUEST_LENGTH = 24;\n/// @dev See Tips.sol: (uint64,uint64,uint64,uint64): 8+8+8+8\nuint256 constant TIPS_LENGTH = 32;\n/// @dev The amount of discarded last bits when encoding tip values\nuint256 constant TIPS_GRANULARITY = 32;\n/// @dev Tip values could be only the multiples of TIPS_MULTIPLIER\nuint256 constant TIPS_MULTIPLIER = 1 \u003c\u003c TIPS_GRANULARITY;\n// ══════════════════════════════ STATEMENT SALTS ══════════════════════════════\n/// @dev Salts for signing various statements\nbytes32 constant ATTESTATION_VALID_SALT = keccak256(\"ATTESTATION_VALID_SALT\");\nbytes32 constant ATTESTATION_INVALID_SALT = keccak256(\"ATTESTATION_INVALID_SALT\");\nbytes32 constant RECEIPT_VALID_SALT = keccak256(\"RECEIPT_VALID_SALT\");\nbytes32 constant RECEIPT_INVALID_SALT = keccak256(\"RECEIPT_INVALID_SALT\");\nbytes32 constant SNAPSHOT_VALID_SALT = keccak256(\"SNAPSHOT_VALID_SALT\");\nbytes32 constant STATE_INVALID_SALT = keccak256(\"STATE_INVALID_SALT\");\n// ═════════════════════════════════ PROTOCOL ══════════════════════════════════\n/// @dev Optimistic period for new agent roots in LightManager\nuint32 constant AGENT_ROOT_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Timeout between the agent root could be proposed and resolved in LightManager\nuint32 constant AGENT_ROOT_PROPOSAL_TIMEOUT = 12 hours;\nuint32 constant BONDING_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Amount of time that the Notary will not be considered active after they won a dispute\nuint32 constant DISPUTE_TIMEOUT_NOTARY = 12 hours;\n/// @dev Amount of time without fresh data from Notaries before contract owner can resolve stuck disputes manually\nuint256 constant FRESH_DATA_TIMEOUT = 4 hours;\n/// @dev Maximum bytes per message = 2 KiB (somewhat arbitrarily set to begin)\nuint256 constant MAX_CONTENT_BYTES = 2 * 2 ** 10;\n/// @dev Maximum value for the summit tip that could be set in GasOracle\nuint256 constant MAX_SUMMIT_TIP = 0.01 ether;\n\n// contracts/libs/Errors.sol\n\n// ══════════════════════════════ INVALID CALLER ═══════════════════════════════\n\nerror CallerNotAgentManager();\nerror CallerNotDestination();\nerror CallerNotInbox();\nerror CallerNotSummit();\n\n// ══════════════════════════════ INCORRECT DATA ═══════════════════════════════\n\nerror IncorrectAttestation();\nerror IncorrectAgentDomain();\nerror IncorrectAgentIndex();\nerror IncorrectAgentProof();\nerror IncorrectAgentRoot();\nerror IncorrectDataHash();\nerror IncorrectDestinationDomain();\nerror IncorrectOriginDomain();\nerror IncorrectSnapshotProof();\nerror IncorrectSnapshotRoot();\nerror IncorrectState();\nerror IncorrectStatesAmount();\nerror IncorrectTipsProof();\nerror IncorrectVersionLength();\n\nerror IncorrectNonce();\nerror IncorrectSender();\nerror IncorrectRecipient();\n\nerror FlagOutOfRange();\nerror IndexOutOfRange();\nerror NonceOutOfRange();\n\nerror OutdatedNonce();\n\nerror UnformattedAttestation();\nerror UnformattedAttestationReport();\nerror UnformattedBaseMessage();\nerror UnformattedCallData();\nerror UnformattedCallDataPrefix();\nerror UnformattedMessage();\nerror UnformattedReceipt();\nerror UnformattedReceiptReport();\nerror UnformattedSignature();\nerror UnformattedSnapshot();\nerror UnformattedState();\nerror UnformattedStateReport();\n\n// ═══════════════════════════════ MERKLE TREES ════════════════════════════════\n\nerror LeafNotProven();\nerror MerkleTreeFull();\nerror NotEnoughLeafs();\nerror TreeHeightTooLow();\n\n// ═════════════════════════════ OPTIMISTIC PERIOD ═════════════════════════════\n\nerror BaseClientOptimisticPeriod();\nerror MessageOptimisticPeriod();\nerror SlashAgentOptimisticPeriod();\nerror WithdrawTipsOptimisticPeriod();\nerror ZeroProofMaturity();\n\n// ═══════════════════════════════ AGENT MANAGER ═══════════════════════════════\n\nerror AgentNotGuard();\nerror AgentNotNotary();\n\nerror AgentCantBeAdded();\nerror AgentNotActive();\nerror AgentNotActiveNorUnstaking();\nerror AgentNotFraudulent();\nerror AgentNotUnstaking();\nerror AgentUnknown();\n\nerror AgentRootNotProposed();\nerror AgentRootTimeoutNotOver();\n\nerror NotStuck();\n\nerror DisputeAlreadyResolved();\nerror DisputeNotOpened();\nerror DisputeTimeoutNotOver();\nerror GuardInDispute();\nerror NotaryInDispute();\n\nerror MustBeSynapseDomain();\nerror SynapseDomainForbidden();\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\nerror AlreadyExecuted();\nerror AlreadyFailed();\nerror DuplicatedSnapshotRoot();\nerror IncorrectMagicValue();\nerror GasLimitTooLow();\nerror GasSuppliedTooLow();\n\n// ══════════════════════════════════ ORIGIN ═══════════════════════════════════\n\nerror ContentLengthTooBig();\nerror EthTransferFailed();\nerror InsufficientEthBalance();\n\n// ════════════════════════════════ GAS ORACLE ═════════════════════════════════\n\nerror LocalGasDataNotSet();\nerror RemoteGasDataNotSet();\n\n// ═══════════════════════════════════ TIPS ════════════════════════════════════\n\nerror SummitTipTooHigh();\nerror TipsClaimMoreThanEarned();\nerror TipsClaimZero();\nerror TipsOverflow();\nerror TipsValueTooLow();\n\n// ════════════════════════════════ MEMORY VIEW ════════════════════════════════\n\nerror IndexedTooMuch();\nerror ViewOverrun();\nerror OccupiedMemory();\nerror UnallocatedMemory();\nerror PrecompileOutOfGas();\n\n// ═════════════════════════════════ MULTICALL ═════════════════════════════════\n\nerror MulticallFailed();\n\n// contracts/libs/TypeCasts.sol\n\nlibrary TypeCasts {\n    // alignment preserving cast\n    function addressToBytes32(address addr) internal pure returns (bytes32) {\n        return bytes32(uint256(uint160(addr)));\n    }\n\n    // alignment preserving cast\n    function bytes32ToAddress(bytes32 buf) internal pure returns (address) {\n        return address(uint160(uint256(buf)));\n    }\n}\n\n// contracts/libs/stack/Number.sol\n\n/// Number is a compact representation of uint256, that is fit into 16 bits\n/// with the maximum relative error under 0.4%.\ntype Number is uint16;\n\nusing NumberLib for Number global;\n\n/// # Number\n/// Library for compact representation of uint256 numbers.\n/// - Number is stored using mantissa and exponent, each occupying 8 bits.\n/// - Numbers under 2**8 are stored as `mantissa` with `exponent = 0xFF`.\n/// - Numbers at least 2**8 are approximated as `(256 + mantissa) \u003c\u003c exponent`\n/// \u003e - `0 \u003c= mantissa \u003c 256`\n/// \u003e - `0 \u003c= exponent \u003c= 247` (`256 * 2**248` doesn't fit into uint256)\n/// # Number stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type  | Bytes |\n/// | ---------- | -------- | ----- | ----- |\n/// | (002..001] | mantissa | uint8 | 1     |\n/// | (001..000] | exponent | uint8 | 1     |\n\nlibrary NumberLib {\n    /// @dev Amount of bits to shift to mantissa field\n    uint16 private constant SHIFT_MANTISSA = 8;\n\n    /// @notice For bwad math (binary wad) we use 2**64 as \"wad\" unit.\n    /// @dev We are using not using 10**18 as wad, because it is not stored precisely in NumberLib.\n    uint256 internal constant BWAD_SHIFT = 64;\n    uint256 internal constant BWAD = 1 \u003c\u003c BWAD_SHIFT;\n    /// @notice ~0.1% in bwad units.\n    uint256 internal constant PER_MILLE_SHIFT = BWAD_SHIFT - 10;\n    uint256 internal constant PER_MILLE = 1 \u003c\u003c PER_MILLE_SHIFT;\n\n    /// @notice Compresses uint256 number into 16 bits.\n    function compress(uint256 value) internal pure returns (Number) {\n        // Find `msb` such as `2**msb \u003c= value \u003c 2**(msb + 1)`\n        uint256 msb = mostSignificantBit(value);\n        // We want to preserve 9 bits of precision.\n        // The highest bit is always 1, so we can skip it.\n        // The remaining 8 highest bits are stored as mantissa.\n        if (msb \u003c 8) {\n            // Value is less than 2**8, so we can use value as mantissa with \"-1\" exponent.\n            return _encode(uint8(value), 0xFF);\n        } else {\n            // We use `msb - 8` as exponent otherwise. Note that `exponent \u003e= 0`.\n            unchecked {\n                uint256 exponent = msb - 8;\n                // Shifting right by `msb-8` bits will shift the \"remaining 8 highest bits\" into the 8 lowest bits.\n                // uint8() will truncate the highest bit.\n                return _encode(uint8(value \u003e\u003e exponent), uint8(exponent));\n            }\n        }\n    }\n\n    /// @notice Decompresses 16 bits number into uint256.\n    /// @dev The outcome is an approximation of the original number: `(value - value / 256) \u003c number \u003c= value`.\n    function decompress(Number number) internal pure returns (uint256 value) {\n        // Isolate 8 highest bits as the mantissa.\n        uint256 mantissa = Number.unwrap(number) \u003e\u003e SHIFT_MANTISSA;\n        // This will truncate the highest bits, leaving only the exponent.\n        uint256 exponent = uint8(Number.unwrap(number));\n        if (exponent == 0xFF) {\n            return mantissa;\n        } else {\n            unchecked {\n                return (256 + mantissa) \u003c\u003c (exponent);\n            }\n        }\n    }\n\n    /// @dev Returns the most significant bit of `x`\n    /// https://solidity-by-example.org/bitwise/\n    function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\n        // To find `msb` we determine it bit by bit, starting from the highest one.\n        // `0 \u003c= msb \u003c= 255`, so we start from the highest bit, 1\u003c\u003c7 == 128.\n        // If `x` is at least 2**128, then the highest bit of `x` is at least 128.\n        // solhint-disable no-inline-assembly\n        assembly {\n            // `f` is set to 1\u003c\u003c7 if `x \u003e= 2**128` and to 0 otherwise.\n            let f := shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\n            // If `x \u003e= 2**128` then set `msb` highest bit to 1 and shift `x` right by 128.\n            // Otherwise, `msb` remains 0 and `x` remains unchanged.\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        // `x` is now at most 2**128 - 1. Continue the same way, the next highest bit is 1\u003c\u003c6 == 64.\n        assembly {\n            // `f` is set to 1\u003c\u003c6 if `x \u003e= 2**64` and to 0 otherwise.\n            let f := shl(6, gt(x, 0xFFFFFFFFFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c5 if `x \u003e= 2**32` and to 0 otherwise.\n            let f := shl(5, gt(x, 0xFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c4 if `x \u003e= 2**16` and to 0 otherwise.\n            let f := shl(4, gt(x, 0xFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c3 if `x \u003e= 2**8` and to 0 otherwise.\n            let f := shl(3, gt(x, 0xFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c2 if `x \u003e= 2**4` and to 0 otherwise.\n            let f := shl(2, gt(x, 0xF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c1 if `x \u003e= 2**2` and to 0 otherwise.\n            let f := shl(1, gt(x, 0x3))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1 if `x \u003e= 2**1` and to 0 otherwise.\n            let f := gt(x, 0x1)\n            msb := or(msb, f)\n        }\n    }\n\n    /// @dev Wraps (mantissa, exponent) pair into Number.\n    function _encode(uint8 mantissa, uint8 exponent) private pure returns (Number) {\n        // Casts below are upcasts, so they are safe.\n        return Number.wrap(uint16(mantissa) \u003c\u003c SHIFT_MANTISSA | uint16(exponent));\n    }\n}\n\n// contracts/libs/stack/Request.sol\n\n/// Request is encoded data with \"message execution request\".\ntype Request is uint192;\n\nusing RequestLib for Request global;\n\n/// Library for formatting _the request part_ of _the base messages_.\n/// - Request represents a message sender requirements for the message execution on the destination chain.\n/// - Request occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n/// \u003e gasDrop field is included for future compatibility and is ignored at the moment.\n///\n/// # Request stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type   | Bytes | Description                                          |\n/// | ---------- | -------- | ------ | ----- | ---------------------------------------------------- |\n/// | (024..012] | gasDrop  | uint96 | 12    | Minimum amount of gas token to drop to the recipient |\n/// | (012..004] | gasLimit | uint64 | 8     | Minimum amount of gas units to supply for execution  |\n/// | (004..000] | version  | uint32 | 4     | Base message version to pass to the recipient        |\n\nlibrary RequestLib {\n    /// @dev Amount of bits to shift to gasDrop field\n    uint192 private constant SHIFT_GAS_DROP = 12 * 8;\n    /// @dev Amount of bits to shift to gasLimit field\n    uint192 private constant SHIFT_GAS_LIMIT = 4 * 8;\n\n    /// @notice Returns an encoded request with the given fields\n    /// @param gasDrop_     Minimum amount of gas token to drop to the recipient (ignored at the moment)\n    /// @param gasLimit_    Minimum amount of gas units to supply for execution\n    /// @param version_     Base message version to pass to the recipient\n    function encodeRequest(uint96 gasDrop_, uint64 gasLimit_, uint32 version_) internal pure returns (Request) {\n        // Casts below are upcasts, so they are safe\n        return Request.wrap(uint192(gasDrop_) \u003c\u003c SHIFT_GAS_DROP | uint192(gasLimit_) \u003c\u003c SHIFT_GAS_LIMIT | version_);\n    }\n\n    /// @notice Wraps the padded encoded request into a Request-typed value.\n    /// @dev The \"padded\" request is simply an encoded request casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded requests\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedRequest) internal pure returns (Request) {\n        // Casting to uint192 will truncate the highest bits, which is the behavior we want\n        return Request.wrap(uint192(paddedRequest));\n    }\n\n    /// @notice Returns the requested of gas token to drop to the recipient.\n    function gasDrop(Request request) internal pure returns (uint96) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return uint96(Request.unwrap(request) \u003e\u003e SHIFT_GAS_DROP);\n    }\n\n    /// @notice Returns the requested minimum amount of gas units to supply for execution.\n    function gasLimit(Request request) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Request.unwrap(request) \u003e\u003e SHIFT_GAS_LIMIT);\n    }\n\n    /// @notice Returns the requested base message version to pass to the recipient.\n    function version(Request request) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Request.unwrap(request));\n    }\n}\n\n// node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        require(value \u003c= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        require(value \u003c= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        require(value \u003c= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value \u003c= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        require(value \u003c= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        require(value \u003c= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        require(value \u003c= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        require(value \u003c= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        require(value \u003c= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        require(value \u003c= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        require(value \u003c= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        require(value \u003c= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        require(value \u003c= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        require(value \u003c= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        require(value \u003c= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value \u003c= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        require(value \u003c= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        require(value \u003c= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        require(value \u003c= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value \u003c= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        require(value \u003c= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        require(value \u003c= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        require(value \u003c= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value \u003c= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        require(value \u003c= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        require(value \u003c= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        require(value \u003c= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value \u003c= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        require(value \u003c= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value \u003c= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value \u003c= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     *\n     * _Available since v3.0._\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value \u003e= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     *\n     * _Available since v3.0._\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value \u003c= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     *\n     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length \u003e 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance \u003e= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance \u003e= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length \u003e 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n\n// contracts/base/MultiCallable.sol\n\n/// @notice Collection of Multicall utilities. Fork of Multicall3:\n/// https://github.com/mds1/multicall/blob/master/src/Multicall3.sol\nabstract contract MultiCallable {\n    struct Call {\n        bool allowFailure;\n        bytes callData;\n    }\n\n    struct Result {\n        bool success;\n        bytes returnData;\n    }\n\n    /// @notice Aggregates a few calls to this contract into one multicall without modifying `msg.sender`.\n    function multicall(Call[] calldata calls) external returns (Result[] memory callResults) {\n        uint256 amount = calls.length;\n        callResults = new Result[](amount);\n        Call calldata call_;\n        for (uint256 i = 0; i \u003c amount;) {\n            call_ = calls[i];\n            Result memory result = callResults[i];\n            // We perform a delegate call to ourselves here. Delegate call does not modify `msg.sender`, so\n            // this will have the same effect as if `msg.sender` performed all the calls themselves one by one.\n            // solhint-disable-next-line avoid-low-level-calls\n            (result.success, result.returnData) = address(this).delegatecall(call_.callData);\n            // solhint-disable-next-line no-inline-assembly\n            assembly {\n                // Revert if the call fails and failure is not allowed\n                // `allowFailure := calldataload(call_)` and `success := mload(result)`\n                if iszero(or(calldataload(call_), mload(result))) {\n                    // Revert with `0x4d6a2328` (function selector for `MulticallFailed()`)\n                    mstore(0x00, 0x4d6a232800000000000000000000000000000000000000000000000000000000)\n                    revert(0x00, 0x04)\n                }\n            }\n            unchecked {\n                ++i;\n            }\n        }\n    }\n}\n\n// contracts/base/Version.sol\n\n/**\n * @title Versioned\n * @notice Version getter for contracts. Doesn't use any storage slots, meaning\n * it will never cause any troubles with the upgradeable contracts. For instance, this contract\n * can be added or removed from the inheritance chain without shifting the storage layout.\n */\nabstract contract Versioned {\n    /**\n     * @notice Struct that is mimicking the storage layout of a string with 32 bytes or less.\n     * Length is limited by 32, so the whole string payload takes two memory words:\n     * @param length    String length\n     * @param data      String characters\n     */\n    struct _ShortString {\n        uint256 length;\n        bytes32 data;\n    }\n\n    /// @dev Length of the \"version string\"\n    uint256 private immutable _length;\n    /// @dev Bytes representation of the \"version string\".\n    /// Strings with length over 32 are not supported!\n    bytes32 private immutable _data;\n\n    constructor(string memory version_) {\n        _length = bytes(version_).length;\n        if (_length \u003e 32) revert IncorrectVersionLength();\n        // bytes32 is left-aligned =\u003e this will store the byte representation of the string\n        // with the trailing zeroes to complete the 32-byte word\n        _data = bytes32(bytes(version_));\n    }\n\n    function version() external view returns (string memory versionString) {\n        // Load the immutable values to form the version string\n        _ShortString memory str = _ShortString(_length, _data);\n        // The only way to do this cast is doing some dirty assembly\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            versionString := str\n        }\n    }\n}\n\n// contracts/libs/ChainContext.sol\n\n/// @notice Library for accessing chain context variables as tightly packed integers.\n/// Messaging contracts should rely on this library for accessing chain context variables\n/// instead of doing the casting themselves.\nlibrary ChainContext {\n    using SafeCast for uint256;\n\n    /// @notice Returns the current block number as uint40.\n    /// @dev Reverts if block number is greater than 40 bits, which is not supposed to happen\n    /// until the block.timestamp overflows (assuming block time is at least 1 second).\n    function blockNumber() internal view returns (uint40) {\n        return block.number.toUint40();\n    }\n\n    /// @notice Returns the current block timestamp as uint40.\n    /// @dev Reverts if block timestamp is greater than 40 bits, which is\n    /// supposed to happen approximately in year 36835.\n    function blockTimestamp() internal view returns (uint40) {\n        return block.timestamp.toUint40();\n    }\n\n    /// @notice Returns the chain id as uint32.\n    /// @dev Reverts if chain id is greater than 32 bits, which is not\n    /// supposed to happen in production.\n    function chainId() internal view returns (uint32) {\n        return block.chainid.toUint32();\n    }\n}\n\n// contracts/libs/Structures.sol\n\n// Here we define common enums and structures to enable their easier reusing later.\n\n// ═══════════════════════════════ AGENT STATUS ════════════════════════════════\n\n/// @dev Potential statuses for the off-chain bonded agent:\n/// - Unknown: never provided a bond =\u003e signature not valid\n/// - Active: has a bond in BondingManager =\u003e signature valid\n/// - Unstaking: has a bond in BondingManager, initiated the unstaking =\u003e signature not valid\n/// - Resting: used to have a bond in BondingManager, successfully unstaked =\u003e signature not valid\n/// - Fraudulent: proven to commit fraud, value in Merkle Tree not updated =\u003e signature not valid\n/// - Slashed: proven to commit fraud, value in Merkle Tree was updated =\u003e signature not valid\n/// Unstaked agent could later be added back to THE SAME domain by staking a bond again.\n/// Honest agent: Unknown -\u003e Active -\u003e unstaking -\u003e Resting -\u003e Active ...\n/// Malicious agent: Unknown -\u003e Active -\u003e Fraudulent -\u003e Slashed\n/// Malicious agent: Unknown -\u003e Active -\u003e Unstaking -\u003e Fraudulent -\u003e Slashed\nenum AgentFlag {\n    Unknown,\n    Active,\n    Unstaking,\n    Resting,\n    Fraudulent,\n    Slashed\n}\n\n/// @notice Struct for storing an agent in the BondingManager contract.\nstruct AgentStatus {\n    AgentFlag flag;\n    uint32 domain;\n    uint32 index;\n}\n// 184 bits available for tight packing\n\nusing StructureUtils for AgentStatus global;\n\n/// @notice Potential statuses of an agent in terms of being in dispute\n/// - None: agent is not in dispute\n/// - Pending: agent is in unresolved dispute\n/// - Slashed: agent was in dispute that lead to agent being slashed\n/// Note: agent who won the dispute has their status reset to None\nenum DisputeFlag {\n    None,\n    Pending,\n    Slashed\n}\n\n/// @notice Struct for storing dispute status of an agent.\n/// @param flag         Dispute flag: None/Pending/Slashed.\n/// @param openedAt     Timestamp when the latest agent dispute was opened (zero if not opened).\n/// @param resolvedAt   Timestamp when the latest agent dispute was resolved (zero if not resolved).\nstruct DisputeStatus {\n    DisputeFlag flag;\n    uint40 openedAt;\n    uint40 resolvedAt;\n}\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\n/// @notice Struct representing the status of Destination contract.\n/// @param snapRootTime     Timestamp when latest snapshot root was accepted\n/// @param agentRootTime    Timestamp when latest agent root was accepted\n/// @param notaryIndex      Index of Notary who signed the latest agent root\nstruct DestinationStatus {\n    uint40 snapRootTime;\n    uint40 agentRootTime;\n    uint32 notaryIndex;\n}\n\n// ═══════════════════════════════ EXECUTION HUB ═══════════════════════════════\n\n/// @notice Potential statuses of the message in Execution Hub.\n/// - None: there hasn't been a valid attempt to execute the message yet\n/// - Failed: there was a valid attempt to execute the message, but recipient reverted\n/// - Success: there was a valid attempt to execute the message, and recipient did not revert\n/// Note: message can be executed until its status is Success\nenum MessageStatus {\n    None,\n    Failed,\n    Success\n}\n\nlibrary StructureUtils {\n    /// @notice Checks that Agent is Active\n    function verifyActive(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active) {\n            revert AgentNotActive();\n        }\n    }\n\n    /// @notice Checks that Agent is Unstaking\n    function verifyUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Unstaking) {\n            revert AgentNotUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Active or Unstaking\n    function verifyActiveUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active \u0026\u0026 status.flag != AgentFlag.Unstaking) {\n            revert AgentNotActiveNorUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Fraudulent\n    function verifyFraudulent(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Fraudulent) {\n            revert AgentNotFraudulent();\n        }\n    }\n\n    /// @notice Checks that Agent is not Unknown\n    function verifyKnown(AgentStatus memory status) internal pure {\n        if (status.flag == AgentFlag.Unknown) {\n            revert AgentUnknown();\n        }\n    }\n}\n\n// contracts/libs/memory/MemView.sol\n\n/// @dev MemView is an untyped view over a portion of memory to be used instead of `bytes memory`\ntype MemView is uint256;\n\n/// @dev Attach library functions to MemView\nusing MemViewLib for MemView global;\n\n/// @notice Library for operations with the memory views.\n/// Forked from https://github.com/summa-tx/memview-sol with several breaking changes:\n/// - The codebase is ported to Solidity 0.8\n/// - Custom errors are added\n/// - The runtime type checking is replaced with compile-time check provided by User-Defined Value Types\n///   https://docs.soliditylang.org/en/latest/types.html#user-defined-value-types\n/// - uint256 is used as the underlying type for the \"memory view\" instead of bytes29.\n///   It is wrapped into MemView custom type in order not to be confused with actual integers.\n/// - Therefore the \"type\" field is discarded, allowing to allocate 16 bytes for both view location and length\n/// - The documentation is expanded\n/// - Library functions unused by the rest of the codebase are removed\n//  - Very pretty code separators are added :)\nlibrary MemViewLib {\n    /// @notice Stack layout for uint256 (from highest bits to lowest)\n    /// (32 .. 16]      loc     16 bytes    Memory address of underlying bytes\n    /// (16 .. 00]      len     16 bytes    Length of underlying bytes\n\n    // ═══════════════════════════════════════════ BUILDING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Instantiate a new untyped memory view. This should generally not be called directly.\n     * Prefer `ref` wherever possible.\n     * @param loc_          The memory address\n     * @param len_          The length\n     * @return The new view with the specified location and length\n     */\n    function build(uint256 loc_, uint256 len_) internal pure returns (MemView) {\n        uint256 end_ = loc_ + len_;\n        // Make sure that a view is not constructed that points to unallocated memory\n        // as this could be indicative of a buffer overflow attack\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            if gt(end_, mload(0x40)) { end_ := 0 }\n        }\n        if (end_ == 0) {\n            revert UnallocatedMemory();\n        }\n        return _unsafeBuildUnchecked(loc_, len_);\n    }\n\n    /**\n     * @notice Instantiate a memory view from a byte array.\n     * @dev Note that due to Solidity memory representation, it is not possible to\n     * implement a deref, as the `bytes` type stores its len in memory.\n     * @param arr           The byte array\n     * @return The memory view over the provided byte array\n     */\n    function ref(bytes memory arr) internal pure returns (MemView) {\n        uint256 len_ = arr.length;\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 loc_;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // We add 0x20, so that the view starts exactly where the array data starts\n            loc_ := add(arr, 0x20)\n        }\n        return build(loc_, len_);\n    }\n\n    // ════════════════════════════════════════════ CLONING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to the new memory.\n     * @param memView       The memory view\n     * @return arr          The cloned byte array\n     */\n    function clone(MemView memView) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        unchecked {\n            _unsafeCopyTo(memView, ptr + 0x20);\n        }\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 len_ = memView.len();\n        uint256 footprint_ = memView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    /**\n     * @notice Copies all views, joins them into a new bytearray.\n     * @param memViews      The memory views\n     * @return arr          The new byte array with joined data behind the given views\n     */\n    function join(MemView[] memory memViews) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        MemView newView;\n        unchecked {\n            newView = _unsafeJoin(memViews, ptr + 0x20);\n        }\n        uint256 len_ = newView.len();\n        uint256 footprint_ = newView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    // ══════════════════════════════════════════ INSPECTING MEMORY VIEW ═══════════════════════════════════════════════\n\n    /**\n     * @notice Returns the memory address of the underlying bytes.\n     * @param memView       The memory view\n     * @return loc_         The memory address\n     */\n    function loc(MemView memView) internal pure returns (uint256 loc_) {\n        // loc is stored in the highest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u003e\u003e 128;\n    }\n\n    /**\n     * @notice Returns the number of bytes of the view.\n     * @param memView       The memory view\n     * @return len_         The length of the view\n     */\n    function len(MemView memView) internal pure returns (uint256 len_) {\n        // len is stored in the lowest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u0026 type(uint128).max;\n    }\n\n    /**\n     * @notice Returns the endpoint of `memView`.\n     * @param memView       The memory view\n     * @return end_         The endpoint of `memView`\n     */\n    function end(MemView memView) internal pure returns (uint256 end_) {\n        // The endpoint never overflows uint128, let alone uint256, so we could use unchecked math here\n        unchecked {\n            return memView.loc() + memView.len();\n        }\n    }\n\n    /**\n     * @notice Returns the number of memory words this memory view occupies, rounded up.\n     * @param memView       The memory view\n     * @return words_       The number of memory words\n     */\n    function words(MemView memView) internal pure returns (uint256 words_) {\n        // returning ceil(length / 32.0)\n        unchecked {\n            return (memView.len() + 31) \u003e\u003e 5;\n        }\n    }\n\n    /**\n     * @notice Returns the in-memory footprint of a fresh copy of the view.\n     * @param memView       The memory view\n     * @return footprint_   The in-memory footprint of a fresh copy of the view.\n     */\n    function footprint(MemView memView) internal pure returns (uint256 footprint_) {\n        // words() * 32\n        return memView.words() \u003c\u003c 5;\n    }\n\n    // ════════════════════════════════════════════ HASHING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the keccak256 hash of the underlying memory\n     * @param memView       The memory view\n     * @return digest       The keccak256 hash of the underlying memory\n     */\n    function keccak(MemView memView) internal pure returns (bytes32 digest) {\n        uint256 loc_ = memView.loc();\n        uint256 len_ = memView.len();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            digest := keccak256(loc_, len_)\n        }\n    }\n\n    /**\n     * @notice Adds a salt to the keccak256 hash of the underlying data and returns the keccak256 hash of the\n     * resulting data.\n     * @param memView       The memory view\n     * @return digestSalted keccak256(salt, keccak256(memView))\n     */\n    function keccakSalted(MemView memView, bytes32 salt) internal pure returns (bytes32 digestSalted) {\n        return keccak256(bytes.concat(salt, memView.keccak()));\n    }\n\n    // ════════════════════════════════════════════ SLICING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Safe slicing without memory modification.\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the given index\n     */\n    function slice(MemView memView, uint256 index_, uint256 len_) internal pure returns (MemView) {\n        uint256 loc_ = memView.loc();\n        // Ensure it doesn't overrun the view\n        if (loc_ + index_ + len_ \u003e memView.end()) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // loc_ + index_ \u003c= memView.end()\n            return build({loc_: loc_ + index_, len_: len_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing bytes from `index` to end(memView).\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @return The new view for the slice starting from the given index until the initial view endpoint\n     */\n    function sliceFrom(MemView memView, uint256 index_) internal pure returns (MemView) {\n        uint256 len_ = memView.len();\n        // Ensure it doesn't overrun the view\n        if (index_ \u003e len_) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // index_ \u003c= len_ =\u003e memView.loc() + index_ \u003c= memView.loc() + memView.len() == memView.end()\n            return build({loc_: memView.loc() + index_, len_: len_ - index_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the first `len` bytes.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the initial view beginning\n     */\n    function prefix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        return memView.slice({index_: 0, len_: len_});\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the last `len` byte.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length until the initial view endpoint\n     */\n    function postfix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        uint256 viewLen = memView.len();\n        // Ensure it doesn't overrun the view\n        if (len_ \u003e viewLen) {\n            revert ViewOverrun();\n        }\n        // Could do the unchecked math due to the check above\n        uint256 index_;\n        unchecked {\n            index_ = viewLen - len_;\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // len_ \u003c= memView.len() =\u003e memView.loc() \u003c= loc_ \u003c= memView.end()\n            return build({loc_: memView.loc() + viewLen - len_, len_: len_});\n        }\n    }\n\n    // ═══════════════════════════════════════════ INDEXING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Load up to 32 bytes from the view onto the stack.\n     * @dev Returns a bytes32 with only the `bytes_` HIGHEST bytes set.\n     * This can be immediately cast to a smaller fixed-length byte array.\n     * To automatically cast to an integer, use `indexUint`.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return result       The 32 byte result having only `bytes_` highest bytes set\n     */\n    function index(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (bytes32 result) {\n        if (bytes_ == 0) {\n            return bytes32(0);\n        }\n        // Can't load more than 32 bytes to the stack in one go\n        if (bytes_ \u003e 32) {\n            revert IndexedTooMuch();\n        }\n        // The last indexed byte should be within view boundaries\n        if (index_ + bytes_ \u003e memView.len()) {\n            revert ViewOverrun();\n        }\n        uint256 bitLength = bytes_ \u003c\u003c 3; // bytes_ * 8\n        uint256 loc_ = memView.loc();\n        // Get a mask with `bitLength` highest bits set\n        uint256 mask;\n        // 0x800...00 binary representation is 100...00\n        // sar stands for \"signed arithmetic shift\": https://en.wikipedia.org/wiki/Arithmetic_shift\n        // sar(N-1, 100...00) = 11...100..00, with exactly N highest bits set to 1\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            mask := sar(sub(bitLength, 1), 0x8000000000000000000000000000000000000000000000000000000000000000)\n        }\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load a full word using index offset, and apply mask to ignore non-relevant bytes\n            result := and(mload(add(loc_, index_)), mask)\n        }\n    }\n\n    /**\n     * @notice Parse an unsigned integer from the view at `index`.\n     * @dev Requires that the view have \u003e= `bytes_` bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return The unsigned integer\n     */\n    function indexUint(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (uint256) {\n        bytes32 indexedBytes = memView.index(index_, bytes_);\n        // `index()` returns left-aligned `bytes_`, while integers are right-aligned\n        // Shifting here to right-align with the full 32 bytes word: need to shift right `(32 - bytes_)` bytes\n        unchecked {\n            // memView.index() reverts when bytes_ \u003e 32, thus unchecked math\n            return uint256(indexedBytes) \u003e\u003e ((32 - bytes_) \u003c\u003c 3);\n        }\n    }\n\n    /**\n     * @notice Parse an address from the view at `index`.\n     * @dev Requires that the view have \u003e= 20 bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @return The address\n     */\n    function indexAddress(MemView memView, uint256 index_) internal pure returns (address) {\n        // index 20 bytes as `uint160`, and then cast to `address`\n        return address(uint160(memView.indexUint(index_, 20)));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns a memory view over the specified memory location\n    /// without checking if it points to unallocated memory.\n    function _unsafeBuildUnchecked(uint256 loc_, uint256 len_) private pure returns (MemView) {\n        // There is no scenario where loc or len would overflow uint128, so we omit this check.\n        // We use the highest 128 bits to encode the location and the lowest 128 bits to encode the length.\n        return MemView.wrap((loc_ \u003c\u003c 128) | len_);\n    }\n\n    /**\n     * @notice Copy the view to a location, return an unsafe memory reference\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memView       The memory view\n     * @param newLoc        The new location to copy the underlying view data\n     * @return The memory view over the unsafe memory with the copied underlying data\n     */\n    function _unsafeCopyTo(MemView memView, uint256 newLoc) private view returns (MemView) {\n        uint256 len_ = memView.len();\n        uint256 oldLoc = memView.loc();\n\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (newLoc \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        bool res;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // use the identity precompile (0x04) to copy\n            res := staticcall(gas(), 0x04, oldLoc, len_, newLoc, len_)\n        }\n        if (!res) revert PrecompileOutOfGas();\n        return _unsafeBuildUnchecked({loc_: newLoc, len_: len_});\n    }\n\n    /**\n     * @notice Join the views in memory, return an unsafe reference to the memory.\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memViews      The memory views\n     * @return The conjoined view pointing to the new memory\n     */\n    function _unsafeJoin(MemView[] memory memViews, uint256 location) private view returns (MemView) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (location \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        // Copy the views to the specified location one by one, by tracking the amount of copied bytes so far\n        uint256 offset = 0;\n        for (uint256 i = 0; i \u003c memViews.length;) {\n            MemView memView = memViews[i];\n            // We can use the unchecked math here as location + sum(view.length) will never overflow uint256\n            unchecked {\n                _unsafeCopyTo(memView, location + offset);\n                offset += memView.len();\n                ++i;\n            }\n        }\n        return _unsafeBuildUnchecked({loc_: location, len_: offset});\n    }\n}\n\n// contracts/libs/merkle/MerkleMath.sol\n\nlibrary MerkleMath {\n    // ═════════════════════════════════════════ BASIC MERKLE CALCULATIONS ═════════════════════════════════════════════\n\n    /**\n     * @notice Calculates the merkle root for the given leaf and merkle proof.\n     * @dev Will revert if proof length exceeds the tree height.\n     * @param index     Index of `leaf` in tree\n     * @param leaf      Leaf of the merkle tree\n     * @param proof     Proof of inclusion of `leaf` in the tree\n     * @param height    Height of the merkle tree\n     * @return root_    Calculated Merkle Root\n     */\n    function proofRoot(uint256 index, bytes32 leaf, bytes32[] memory proof, uint256 height)\n        internal\n        pure\n        returns (bytes32 root_)\n    {\n        // Proof length could not exceed the tree height\n        uint256 proofLen = proof.length;\n        if (proofLen \u003e height) revert TreeHeightTooLow();\n        root_ = leaf;\n        /// @dev Apply unchecked to all ++h operations\n        unchecked {\n            // Go up the tree levels from the leaf following the proof\n            for (uint256 h = 0; h \u003c proofLen; ++h) {\n                // Get a sibling node on current level: this is proof[h]\n                root_ = getParent(root_, proof[h], index, h);\n            }\n            // Go up to the root: the remaining siblings are EMPTY\n            for (uint256 h = proofLen; h \u003c height; ++h) {\n                root_ = getParent(root_, bytes32(0), index, h);\n            }\n        }\n    }\n\n    /**\n     * @notice Calculates the parent of a node on the path from one of the leafs to root.\n     * @param node          Node on a path from tree leaf to root\n     * @param sibling       Sibling for a given node\n     * @param leafIndex     Index of the tree leaf\n     * @param nodeHeight    \"Level height\" for `node` (ZERO for leafs, ORIGIN_TREE_HEIGHT for root)\n     */\n    function getParent(bytes32 node, bytes32 sibling, uint256 leafIndex, uint256 nodeHeight)\n        internal\n        pure\n        returns (bytes32 parent)\n    {\n        // Index for `node` on its \"tree level\" is (leafIndex / 2**height)\n        // \"Left child\" has even index, \"right child\" has odd index\n        if ((leafIndex \u003e\u003e nodeHeight) \u0026 1 == 0) {\n            // Left child\n            return getParent(node, sibling);\n        } else {\n            // Right child\n            return getParent(sibling, node);\n        }\n    }\n\n    /// @notice Calculates the parent of tow nodes in the merkle tree.\n    /// @dev We use implementation with H(0,0) = 0\n    /// This makes EVERY empty node in the tree equal to ZERO,\n    /// saving us from storing H(0,0), H(H(0,0), H(0, 0)), and so on\n    /// @param leftChild    Left child of the calculated node\n    /// @param rightChild   Right child of the calculated node\n    /// @return parent      Value for the node having above mentioned children\n    function getParent(bytes32 leftChild, bytes32 rightChild) internal pure returns (bytes32 parent) {\n        if (leftChild == bytes32(0) \u0026\u0026 rightChild == bytes32(0)) {\n            return 0;\n        } else {\n            return keccak256(bytes.concat(leftChild, rightChild));\n        }\n    }\n\n    // ════════════════════════════════ ROOT/PROOF CALCULATION FOR A LIST OF LEAFS ═════════════════════════════════════\n\n    /**\n     * @notice Calculates merkle root for a list of given leafs.\n     * Merkle Tree is constructed by padding the list with ZERO values for leafs until list length is `2**height`.\n     * Merkle Root is calculated for the constructed tree, and then saved in `leafs[0]`.\n     * \u003e Note:\n     * \u003e - `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * \u003e - Caller is expected not to reuse `hashes` list after the call, and only use `leafs[0]` value,\n     * which is guaranteed to contain the calculated merkle root.\n     * \u003e - root is calculated using the `H(0,0) = 0` Merkle Tree implementation. See MerkleTree.sol for details.\n     * @dev Amount of leaves should be at most `2**height`\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param height    Height of the Merkle Tree to construct\n     */\n    function calculateRoot(bytes32[] memory hashes, uint256 height) internal pure {\n        uint256 levelLength = hashes.length;\n        // Amount of hashes could not exceed amount of leafs in tree with the given height\n        if (levelLength \u003e (1 \u003c\u003c height)) revert TreeHeightTooLow();\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\": the amount of iterations for the for loop above.\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n            }\n        }\n    }\n\n    /**\n     * @notice Generates a proof of inclusion of a leaf in the list. If the requested index is outside\n     * of the list range, generates a proof of inclusion for an empty leaf (proof of non-inclusion).\n     * The Merkle Tree is constructed by padding the list with ZERO values until list length is a power of two\n     * __AND__ index is in the extended list range. For example:\n     *  - `hashes.length == 6` and `0 \u003c= index \u003c= 7` will \"extend\" the list to 8 entries.\n     *  - `hashes.length == 6` and `7 \u003c index \u003c= 15` will \"extend\" the list to 16 entries.\n     * \u003e Note: `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * Caller is expected not to reuse `hashes` list after the call.\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param index     Leaf index to generate the proof for\n     * @return proof    Generated merkle proof\n     */\n    function calculateProof(bytes32[] memory hashes, uint256 index) internal pure returns (bytes32[] memory proof) {\n        // Use only meaningful values for the shortened proof\n        // Check if index is within the list range (we want to generates proofs for outside leafs as well)\n        uint256 height = getHeight(index \u003c hashes.length ? hashes.length : (index + 1));\n        proof = new bytes32[](height);\n        uint256 levelLength = hashes.length;\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Use sibling for the merkle proof; `index^1` is index of our sibling\n                proof[h] = (index ^ 1 \u003c levelLength) ? hashes[index ^ 1] : bytes32(0);\n\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\"\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n                // Traverse to parent node\n                index \u003e\u003e= 1;\n            }\n        }\n    }\n\n    /// @notice Returns the height of the tree having a given amount of leafs.\n    function getHeight(uint256 leafs) internal pure returns (uint256 height) {\n        uint256 amount = 1;\n        while (amount \u003c leafs) {\n            unchecked {\n                ++height;\n            }\n            amount \u003c\u003c= 1;\n        }\n    }\n}\n\n// contracts/libs/stack/GasData.sol\n\n/// GasData in encoded data with \"basic information about gas prices\" for some chain.\ntype GasData is uint96;\n\nusing GasDataLib for GasData global;\n\n/// ChainGas is encoded data with given chain's \"basic information about gas prices\".\ntype ChainGas is uint128;\n\nusing GasDataLib for ChainGas global;\n\n/// Library for encoding and decoding GasData and ChainGas structs.\n/// # GasData\n/// `GasData` is a struct to store the \"basic information about gas prices\", that could\n/// be later used to approximate the cost of a message execution, and thus derive the\n/// minimal tip values for sending a message to the chain.\n/// \u003e - `GasData` is supposed to be cached by `GasOracle` contract, allowing to store the\n/// \u003e approximates instead of the exact values, and thus save on storage costs.\n/// \u003e - For instance, if `GasOracle` only updates the values on +- 10% change, having an\n/// \u003e 0.4% error on the approximates would be acceptable.\n/// `GasData` is supposed to be included in the Origin's state, which are synced across\n/// chains using Agent-signed snapshots and attestations.\n/// ## GasData stack layout (from highest bits to lowest)\n///\n/// | Position   | Field        | Type   | Bytes | Description                                         |\n/// | ---------- | ------------ | ------ | ----- | --------------------------------------------------- |\n/// | (012..010] | gasPrice     | uint16 | 2     | Gas price for the chain (in Wei per gas unit)       |\n/// | (010..008] | dataPrice    | uint16 | 2     | Calldata price (in Wei per byte of content)         |\n/// | (008..006] | execBuffer   | uint16 | 2     | Tx fee safety buffer for message execution (in Wei) |\n/// | (006..004] | amortAttCost | uint16 | 2     | Amortized cost for attestation submission (in Wei)  |\n/// | (004..002] | etherPrice   | uint16 | 2     | Chain's Ether Price / Mainnet Ether Price (in BWAD) |\n/// | (002..000] | markup       | uint16 | 2     | Markup for the message execution (in BWAD)          |\n/// \u003e See Number.sol for more details on `Number` type and BWAD (binary WAD) math.\n///\n/// ## ChainGas stack layout (from highest bits to lowest)\n///\n/// | Position   | Field   | Type   | Bytes | Description      |\n/// | ---------- | ------- | ------ | ----- | ---------------- |\n/// | (016..004] | gasData | uint96 | 12    | Chain's gas data |\n/// | (004..000] | domain  | uint32 | 4     | Chain's domain   |\nlibrary GasDataLib {\n    /// @dev Amount of bits to shift to gasPrice field\n    uint96 private constant SHIFT_GAS_PRICE = 10 * 8;\n    /// @dev Amount of bits to shift to dataPrice field\n    uint96 private constant SHIFT_DATA_PRICE = 8 * 8;\n    /// @dev Amount of bits to shift to execBuffer field\n    uint96 private constant SHIFT_EXEC_BUFFER = 6 * 8;\n    /// @dev Amount of bits to shift to amortAttCost field\n    uint96 private constant SHIFT_AMORT_ATT_COST = 4 * 8;\n    /// @dev Amount of bits to shift to etherPrice field\n    uint96 private constant SHIFT_ETHER_PRICE = 2 * 8;\n\n    /// @dev Amount of bits to shift to gasData field\n    uint128 private constant SHIFT_GAS_DATA = 4 * 8;\n\n    // ═════════════════════════════════════════════════ GAS DATA ══════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded GasData struct with the given fields.\n    /// @param gasPrice_        Gas price for the chain (in Wei per gas unit)\n    /// @param dataPrice_       Calldata price (in Wei per byte of content)\n    /// @param execBuffer_      Tx fee safety buffer for message execution (in Wei)\n    /// @param amortAttCost_    Amortized cost for attestation submission (in Wei)\n    /// @param etherPrice_      Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n    /// @param markup_          Markup for the message execution (in BWAD)\n    function encodeGasData(\n        Number gasPrice_,\n        Number dataPrice_,\n        Number execBuffer_,\n        Number amortAttCost_,\n        Number etherPrice_,\n        Number markup_\n    ) internal pure returns (GasData) {\n        // Number type wraps uint16, so could safely be casted to uint96\n        // forgefmt: disable-next-item\n        return GasData.wrap(\n            uint96(Number.unwrap(gasPrice_)) \u003c\u003c SHIFT_GAS_PRICE |\n            uint96(Number.unwrap(dataPrice_)) \u003c\u003c SHIFT_DATA_PRICE |\n            uint96(Number.unwrap(execBuffer_)) \u003c\u003c SHIFT_EXEC_BUFFER |\n            uint96(Number.unwrap(amortAttCost_)) \u003c\u003c SHIFT_AMORT_ATT_COST |\n            uint96(Number.unwrap(etherPrice_)) \u003c\u003c SHIFT_ETHER_PRICE |\n            uint96(Number.unwrap(markup_))\n        );\n    }\n\n    /// @notice Wraps padded uint256 value into GasData struct.\n    function wrapGasData(uint256 paddedGasData) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(paddedGasData));\n    }\n\n    /// @notice Returns the gas price, in Wei per gas unit.\n    function gasPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_GAS_PRICE));\n    }\n\n    /// @notice Returns the calldata price, in Wei per byte of content.\n    function dataPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_DATA_PRICE));\n    }\n\n    /// @notice Returns the tx fee safety buffer for message execution, in Wei.\n    function execBuffer(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_EXEC_BUFFER));\n    }\n\n    /// @notice Returns the amortized cost for attestation submission, in Wei.\n    function amortAttCost(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_AMORT_ATT_COST));\n    }\n\n    /// @notice Returns the ratio of Chain's Ether Price / Mainnet Ether Price, in BWAD math.\n    function etherPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_ETHER_PRICE));\n    }\n\n    /// @notice Returns the markup for the message execution, in BWAD math.\n    function markup(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data)));\n    }\n\n    // ════════════════════════════════════════════════ CHAIN DATA ═════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded ChainGas struct with the given fields.\n    /// @param gasData_ Chain's gas data\n    /// @param domain_  Chain's domain\n    function encodeChainGas(GasData gasData_, uint32 domain_) internal pure returns (ChainGas) {\n        // GasData type wraps uint96, so could safely be casted to uint128\n        return ChainGas.wrap(uint128(GasData.unwrap(gasData_)) \u003c\u003c SHIFT_GAS_DATA | uint128(domain_));\n    }\n\n    /// @notice Wraps padded uint256 value into ChainGas struct.\n    function wrapChainGas(uint256 paddedChainGas) internal pure returns (ChainGas) {\n        // Casting to uint128 will truncate the highest bits, which is the behavior we want\n        return ChainGas.wrap(uint128(paddedChainGas));\n    }\n\n    /// @notice Returns the chain's gas data.\n    function gasData(ChainGas data) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(ChainGas.unwrap(data) \u003e\u003e SHIFT_GAS_DATA));\n    }\n\n    /// @notice Returns the chain's domain.\n    function domain(ChainGas data) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(ChainGas.unwrap(data));\n    }\n\n    /// @notice Returns the hash for the list of ChainGas structs.\n    function snapGasHash(ChainGas[] memory snapGas) internal pure returns (bytes32 snapGasHash_) {\n        // Use assembly to calculate the hash of the array without copying it\n        // ChainGas takes a single word of storage, thus ChainGas[] is stored in the following way:\n        // 0x00: length of the array, in words\n        // 0x20: first ChainGas struct\n        // 0x40: second ChainGas struct\n        // And so on...\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Find the location where the array data starts, we add 0x20 to skip the length field\n            let loc := add(snapGas, 0x20)\n            // Load the length of the array (in words).\n            // Shifting left 5 bits is equivalent to multiplying by 32: this converts from words to bytes.\n            let len := shl(5, mload(snapGas))\n            // Calculate the hash of the array\n            snapGasHash_ := keccak256(loc, len)\n        }\n    }\n}\n\n// contracts/libs/stack/Header.sol\n\n/// Header is encoded data with \"general routing information\".\ntype Header is uint136;\n\nusing HeaderLib for Header global;\n\n/// Types of messages supported by Origin-Destination\n/// - Base: message sent by protocol user, contains tips\n/// - Manager: message sent between AgentManager contracts located on different chains, no tips\nenum MessageFlag {\n    Base,\n    Manager\n}\n\nusing HeaderLib for MessageFlag global;\n\n/// Library for formatting _the header part_ of _the messages used by Origin and Destination_.\n/// - Header represents general information for routing a Message for Origin and Destination.\n/// - Header occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n///\n/// # Header stack layout (from highest bits to lowest)\n///\n/// | Position   | Field            | Type   | Bytes | Description                             |\n/// | ---------- | ---------------- | ------ | ----- | --------------------------------------- |\n/// | (017..016] | flag             | uint8  | 1     | Flag specifying the type of message     |\n/// | (016..012] | origin           | uint32 | 4     | Domain where message originated         |\n/// | (012..008] | nonce            | uint32 | 4     | Message nonce on the origin domain      |\n/// | (008..004] | destination      | uint32 | 4     | Domain where message will be executed   |\n/// | (004..000] | optimisticPeriod | uint32 | 4     | Optimistic period that will be enforced |\nlibrary HeaderLib {\n    /// @dev Amount of bits to shift to flag field\n    uint136 private constant SHIFT_FLAG = 16 * 8;\n    /// @dev Amount of bits to shift to origin field\n    uint136 private constant SHIFT_ORIGIN = 12 * 8;\n    /// @dev Amount of bits to shift to nonce field\n    uint136 private constant SHIFT_NONCE = 8 * 8;\n    /// @dev Amount of bits to shift to destination field\n    uint136 private constant SHIFT_DESTINATION = 4 * 8;\n\n    /// @notice Returns an encoded header with provided fields\n    /// @param origin_              Domain of origin chain\n    /// @param nonce_               Message nonce on origin chain\n    /// @param destination_         Domain of destination chain\n    /// @param optimisticPeriod_    Optimistic period for message execution\n    function encodeHeader(\n        MessageFlag flag_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint32 destination_,\n        uint32 optimisticPeriod_\n    ) internal pure returns (Header) {\n        // All casts below are upcasts, so they are safe\n        // forgefmt: disable-next-item\n        return Header.wrap(\n            uint136(uint8(flag_)) \u003c\u003c SHIFT_FLAG |\n            uint136(origin_) \u003c\u003c SHIFT_ORIGIN |\n            uint136(nonce_) \u003c\u003c SHIFT_NONCE |\n            uint136(destination_) \u003c\u003c SHIFT_DESTINATION |\n            uint136(optimisticPeriod_)\n        );\n    }\n\n    /// @notice Checks that the header is a valid encoded header.\n    function isHeader(uint256 paddedHeader) internal pure returns (bool) {\n        // Check that flag is within range\n        return _flag(paddedHeader) \u003c= uint8(type(MessageFlag).max);\n    }\n\n    /// @notice Wraps the padded encoded request into a Header-typed value.\n    /// @dev The \"padded\" header is simply an encoded header casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded headers\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedHeader) internal pure returns (Header) {\n        // Check that flag is within range\n        if (!isHeader(paddedHeader)) revert FlagOutOfRange();\n        // Casting to uint136 will truncate the highest bits, which is the behavior we want\n        return Header.wrap(uint136(paddedHeader));\n    }\n\n    /// @notice Returns header's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Header header) internal pure returns (bytes32 hashedHeader) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store header in scratch space\n            mstore(0, header)\n            // Compute hash of header padded to 32 bytes\n            hashedHeader := keccak256(0, 32)\n        }\n    }\n\n    // ══════════════════════════════════════════════ HEADER SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns header's flag field\n    function flag(Header header) internal pure returns (MessageFlag) {\n        // We check that flag is within range when wrapping the header, so this cast is safe\n        return MessageFlag(_flag(Header.unwrap(header)));\n    }\n\n    /// @notice Returns header's origin field\n    function origin(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_ORIGIN);\n    }\n\n    /// @notice Returns header's nonce field\n    function nonce(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_NONCE);\n    }\n\n    /// @notice Returns header's destination field\n    function destination(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_DESTINATION);\n    }\n\n    /// @notice Returns header's optimistic seconds field\n    function optimisticPeriod(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns header's flag field without casting to MessageFlag\n    function _flag(uint256 paddedHeader) private pure returns (uint8) {\n        // Casting to uint8 will truncate the highest bits, which is the behavior we want\n        return uint8(paddedHeader \u003e\u003e SHIFT_FLAG);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n     * constructor.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall \u0026\u0026 _initialized \u003c 1) || (!AddressUpgradeable.isContract(address(this)) \u0026\u0026 _initialized == 1),\n            \"Initializable: contract is already initialized\"\n        );\n        _initialized = 1;\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: setting the version to 255 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing \u0026\u0026 _initialized \u003c version, \"Initializable: contract is already initialized\");\n        _initialized = version;\n        _initializing = true;\n        _;\n        _initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        require(_initializing, \"Initializable: contract is not initializing\");\n        _;\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized != type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint8) {\n        return _initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _initializing;\n    }\n}\n\n// contracts/interfaces/IAgentManager.sol\n\ninterface IAgentManager {\n    /**\n     * @notice Allows Inbox to open a Dispute between a Guard and a Notary, if they are both not in Dispute already.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Guard or Notary is already in Dispute.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Allows Inbox to slash an agent, if their fraud was proven.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Domain doesn't match the saved agent domain.\n     * @param domain    Domain where the Agent is active\n     * @param agent     Address of the Agent\n     * @param prover    Address that initially provided fraud proof\n     */\n    function slashAgent(uint32 domain, address agent, address prover) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest known root of the Agent Merkle Tree.\n     */\n    function agentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns the number of opened Disputes.\n     * @dev This includes the Disputes that have been resolved already.\n     */\n    function getDisputesAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns information about the dispute with the given index.\n     * @dev Will revert if dispute with given index hasn't been opened yet.\n     * @param index             Dispute index\n     * @return guard            Address of the Guard in the Dispute\n     * @return notary           Address of the Notary in the Dispute\n     * @return slashedAgent     Address of the Agent who was slashed when Dispute was resolved\n     * @return fraudProver      Address who provided fraud proof to resolve the Dispute\n     * @return reportPayload    Raw payload with report data that led to the Dispute\n     * @return reportSignature  Guard signature for the report payload\n     */\n    function getDispute(uint256 index)\n        external\n        view\n        returns (\n            address guard,\n            address notary,\n            address slashedAgent,\n            address fraudProver,\n            bytes memory reportPayload,\n            bytes memory reportSignature\n        );\n\n    /**\n     * @notice Returns the current Dispute status of a given agent. See Structures.sol for details.\n     * @dev Every returned value will be set to zero if agent was not slashed and is not in Dispute.\n     * `rival` and `disputePtr` will be set to zero if the agent was slashed without being in Dispute.\n     * @param agent         Agent address\n     * @return flag         Flag describing the current Dispute status for the agent: None/Pending/Slashed\n     * @return rival        Address of the rival agent in the Dispute\n     * @return fraudProver  Address who provided fraud proof to resolve the Dispute\n     * @return disputePtr   Index of the opened Dispute PLUS ONE. Zero if agent is not in Dispute.\n     */\n    function disputeStatus(address agent)\n        external\n        view\n        returns (DisputeFlag flag, address rival, address fraudProver, uint256 disputePtr);\n}\n\n// contracts/interfaces/IAgentSecured.sol\n\ninterface IAgentSecured {\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * between a Guard and a Notary has been opened.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * has been resolved due to one of the agents being slashed.\n     * \u003e `rivalIndex` will be ZERO, if the slashed agent was not in the Dispute.\n     * @param slashedIndex  Index of the slashed agent in the Agent Merkle Tree\n     * @param rivalIndex    Index of the their Dispute Rival in the Agent Merkle Tree\n     */\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the address of the local AgentManager contract, which is treated as\n     * the \"source of truth\" for agent statuses.\n     */\n    function agentManager() external view returns (address);\n\n    /**\n     * @notice Returns the address of the local Inbox contract, which is treated as\n     * the \"source of truth\" for agent-signed statements.\n     * @dev Inbox passes verified agent statements to `IAgentSecured` contract.\n     */\n    function inbox() external view returns (address);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns (flag, openedAt, resolvedAt) that describes the latest status of\n     * the latest dispute for an agent with a given index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param agentIndex    Agent index in the Agent Merkle Tree\n     * @return              Latest dispute status for the given agent: (flag, openedAt, resolvedAt)\n     */\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory);\n}\n\n// contracts/libs/memory/ByteString.sol\n\n/// @dev CallData is a memory view over the payload to be used for an external call, i.e.\n/// recipient.call(callData). Its length is always (4 + 32 * N) bytes:\n/// - First 4 bytes represent the function selector.\n/// - 32 * N bytes represent N words that function arguments occupy.\ntype CallData is uint256;\n\n/// @dev Attach library functions to CallData\nusing ByteString for CallData global;\n\n/// @dev Signature is a memory view over a \"65 bytes\" array representing a ECDSA signature.\ntype Signature is uint256;\n\n/// @dev Attach library functions to Signature\nusing ByteString for Signature global;\n\nlibrary ByteString {\n    using MemViewLib for bytes;\n\n    /**\n     * @dev non-compact ECDSA signatures are enforced as of OZ 4.7.3\n     *\n     *      Signature payload memory layout\n     * [000 .. 032) r   bytes32 32 bytes\n     * [032 .. 064) s   bytes32 32 bytes\n     * [064 .. 065) v   uint8    1 byte\n     */\n    uint256 internal constant SIGNATURE_LENGTH = 65;\n    uint256 private constant OFFSET_R = 0;\n    uint256 private constant OFFSET_S = 32;\n    uint256 private constant OFFSET_V = 64;\n\n    /**\n     * @dev Calldata memory layout\n     * [000 .. 004) selector    bytes4  4 bytes\n     *      Optional: N function arguments\n     * [004 .. 036) arg1        bytes32 32 bytes\n     *      ..\n     * [AAA .. END) argN        bytes32 32 bytes\n     */\n    uint256 internal constant SELECTOR_LENGTH = 4;\n    uint256 private constant OFFSET_SELECTOR = 0;\n    uint256 private constant OFFSET_ARGUMENTS = SELECTOR_LENGTH;\n\n    // ═════════════════════════════════════════════════ SIGNATURE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the signature payload from the given values.\n     * @dev Using ByteString.formatSignature({r: r, s: s, v: v}) will make sure\n     * that params are given in the right order.\n     */\n    function formatSignature(bytes32 r, bytes32 s, uint8 v) internal pure returns (bytes memory) {\n        return abi.encodePacked(r, s, v);\n    }\n\n    /**\n     * @notice Returns a Signature view over for the given payload.\n     * @dev Will revert if the payload is not a signature.\n     */\n    function castToSignature(bytes memory payload) internal pure returns (Signature) {\n        return castToSignature(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Signature view.\n     * @dev Will revert if the memory view is not over a signature.\n     */\n    function castToSignature(MemView memView) internal pure returns (Signature) {\n        if (!isSignature(memView)) revert UnformattedSignature();\n        return Signature.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a signature\n     */\n    function isSignature(MemView memView) internal pure returns (bool) {\n        return memView.len() == SIGNATURE_LENGTH;\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Signature signature) internal pure returns (MemView) {\n        return MemView.wrap(Signature.unwrap(signature));\n    }\n\n    // ═════════════════════════════════════════════ SIGNATURE SLICING ═════════════════════════════════════════════════\n\n    /// @notice Unpacks signature payload into (r, s, v) parameters.\n    /// @dev Make sure to verify signature length with isSignature() beforehand.\n    function toRSV(Signature signature) internal pure returns (bytes32 r, bytes32 s, uint8 v) {\n        // Get the underlying memory view\n        MemView memView = unwrap(signature);\n        r = memView.index({index_: OFFSET_R, bytes_: 32});\n        s = memView.index({index_: OFFSET_S, bytes_: 32});\n        // Can be safely casted to uint8, since we index a single byte\n        v = uint8(memView.indexUint({index_: OFFSET_V, bytes_: 1}));\n    }\n\n    // ═════════════════════════════════════════════════ CALLDATA ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the calldata with the modified arguments:\n     * the existing arguments are prepended with the arguments from the prefix.\n     * @dev Given:\n     *  - `calldata = abi.encodeWithSelector(foo.selector, d, e);`\n     *  - `prefix = abi.encode(a, b, c);`\n     *  - `a`, `b`, `c` are arguments of static type (i.e. not dynamically sized ones)\n     *      Then:\n     *  - Function will return abi.encodeWithSelector(foo.selector, a, c, c, d, e)\n     *  - Returned calldata will trigger `foo(a, b, c, d, e)` when used for a contract call.\n     * Note: for clarification as to what types are considered static, see\n     * https://docs.soliditylang.org/en/latest/abi-spec.html#formal-specification-of-the-encoding\n     * @param callData  Calldata that needs to be modified\n     * @param prefix    ABI-encoded arguments to use as the first arguments in the new calldata\n     * @return Modified calldata having prefix as the first arguments.\n     */\n    function addPrefix(CallData callData, bytes memory prefix) internal view returns (bytes memory) {\n        // Prefix should occupy a whole amount of words in memory\n        if (!_fullWords(prefix.length)) revert UnformattedCallDataPrefix();\n        MemView[] memory views = new MemView[](3);\n        // Use payload's function selector\n        views[0] = abi.encodePacked(callData.callSelector()).ref();\n        // Use prefix as the first arguments\n        views[1] = prefix.ref();\n        // Use payload's remaining arguments\n        views[2] = callData.arguments();\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a CallData view over for the given payload.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(bytes memory payload) internal pure returns (CallData) {\n        return castToCallData(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a CallData view.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(MemView memView) internal pure returns (CallData) {\n        if (!isCallData(memView)) revert UnformattedCallData();\n        return CallData.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a valid calldata, i.e.\n     * a function selector, followed by arbitrary amount of arguments.\n     */\n    function isCallData(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Calldata should at least have a function selector\n        if (length \u003c SELECTOR_LENGTH) return false;\n        // The remainder of the calldata should be exactly N memory words (N \u003e= 0)\n        return _fullWords(length - SELECTOR_LENGTH);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(CallData callData) internal pure returns (MemView) {\n        return MemView.wrap(CallData.unwrap(callData));\n    }\n\n    /// @notice Returns callData's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(CallData callData) internal pure returns (bytes32) {\n        return callData.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ CALLDATA SLICING ══════════════════════════════════════════════════\n\n    /**\n     * @notice Returns amount of memory words (32 byte chunks) the function arguments\n     * occupy in the calldata.\n     * @dev This might differ from amount of arguments supplied, if any of the arguments\n     * occupies more than one memory slot. It is true, however, that argument part of the payload\n     * occupies exactly N words, even for dynamic types like `bytes`\n     */\n    function argumentWords(CallData callData) internal pure returns (uint256) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        // Equivalent of (length - SELECTOR_LENGTH) / 32\n        return (memView.len() - SELECTOR_LENGTH) \u003e\u003e 5;\n    }\n\n    /// @notice Returns selector for the provided calldata.\n    function callSelector(CallData callData) internal pure returns (bytes4) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return bytes4(memView.index({index_: OFFSET_SELECTOR, bytes_: SELECTOR_LENGTH}));\n    }\n\n    /// @notice Returns abi encoded arguments for the provided calldata.\n    function arguments(CallData callData) internal pure returns (MemView) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return memView.sliceFrom({index_: OFFSET_ARGUMENTS});\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if length is full amount of memory words (32 bytes).\n    function _fullWords(uint256 length) internal pure returns (bool) {\n        // The equivalent of length % 32 == 0\n        return length \u0026 31 == 0;\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n    function __Context_init() internal onlyInitializing {\n    }\n\n    function __Context_init_unchained() internal onlyInitializing {\n    }\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[50] private __gap;\n}\n\n// contracts/libs/merkle/MerkleTree.sol\n\n/// `BaseTree` is a struct representing incremental merkle tree.\n/// - Contains only the current branch.\n/// - The number of inserted leaves is stored externally, and is later supplied for tree operations.\n/// - Has a fixed height of `ORIGIN_TREE_HEIGHT`.\n/// - Can store up to `2 ** ORIGIN_TREE_HEIGHT - 1` leaves.\n/// \u003e Note: the hash function for the tree `H(x, y)` is defined as:\n/// \u003e - `H(0,0) = 0`\n/// \u003e - `H(x,y) = keccak256(x, y), when (x != 0 || y != 0)`\n/// ## Invariant for leafs\n/// - The leftmost empty leaf has `index == count`, where `count` is the amount of the inserted leafs so far.\n/// - Value for any empty leaf or node is bytes32(0).\n/// ## Invariant for current branch\n/// `branch[i]` is always the value of a node on the i-th level.\n/// Levels are numbered from leafs to root: `0 .. ORIGIN_TREE_HEIGHT`.\n/// `branch[i]` stores the value for the node, such that:\n//  - The node is a \"left child\" (e.g. has an even index).\n/// - The node must have two non-empty children.\n/// - Out of all level's \"left child\" nodes with \"non-empty children\",\n/// the one with the biggest index (the rightmost one) is stored as `branch[i]`.\n/// \u003e __`branch` could be used to form a proof of inclusion for the first empty leaf (`index == count`).__\n/// _Here is how:_\n/// - Let's walk along the path from the \"first empty leaf\" to the root.\n/// - i-th bit of the \"first empty leaf\" index (which is equal to `count`) determines if the path's node\n/// for this i-th level is a \"left child\" or a \"right child\".\n/// - i-th bit in `count` is 0 → we are the left child on this level → sibling is the right child\n/// that does not exist yet → `proof[i] = bytes32(0)`.\n/// - i-th bit in `count` is 1 → we are the right child on this level → sibling is the left child\n/// sibling is the rightmost \"left child\" node on the level → `proof[i] = branch[i]`.\n/// \u003e Therefore `proof[i] = (count \u0026 (1 \u003c\u003c i)) == 0 ? bytes32(0) : branch[i])`\nstruct BaseTree {\n    bytes32[ORIGIN_TREE_HEIGHT] branch;\n}\n\nusing MerkleTree for BaseTree global;\n\n/// `HistoricalTree` is an incremental merkle tree keeping track of its historical merkle roots.\n/// \u003e - `roots[N]` is the root of the tree after `N` leafs were inserted\n/// \u003e - `roots[0] == bytes32(0)`\n/// @param tree     Incremental merkle tree\n/// @param roots    Historical merkle roots of the tree\nstruct HistoricalTree {\n    BaseTree tree;\n    bytes32[] roots;\n}\n\nusing MerkleTree for HistoricalTree global;\n\n/// `DynamicTree` is a struct representing a Merkle Tree with `2**AGENT_TREE_HEIGHT` leaves.\n/// - A single operation is available: update value for leaf with an arbitrary index (which might be a non-empty leaf).\n/// - This is done by requesting the proof of inclusion for the old value, which is used to both\n/// verify the old value, and calculate the new root.\n/// \u003e Based on Original idea from [ER forum post](https://ethresear.ch/t/efficient-on-chain-dynamic-merkle-tree/11054).\nstruct DynamicTree {\n    bytes32 root;\n}\n\nusing MerkleTree for DynamicTree global;\n\n/// MerkleTree is work based on Nomad's Merkle.sol, which is used under MIT OR Apache-2.0\n/// [link](https://github.com/nomad-xyz/monorepo/blob/main/packages/contracts-core/contracts/libs/Merkle.sol).\n/// With the following changes:\n/// - Adapted for Solidity 0.8.x.\n/// - Amount of tree leaves stored externally.\n/// - Added thorough documentation.\n/// - `H(0,0) = 0` optimization from [ER forum post](https://ethresear.ch/t/optimizing-sparse-merkle-trees/3751/6).\n/// \u003e Nomad's Merkle.sol is work based on eth2 deposit contract, which is used under CC0-1.0\n///[link](https://github.com/ethereum/deposit_contract/blob/dev/deposit_contract/contracts/validator_registration.v.py).\n/// With the following changes:\n/// \u003e - Implemented in Solidity 0.7.6 (eth2 deposit contract implemented in Vyper).\n/// \u003e - `H() = keccak256()` is used as the hashing function instead of `sha256()`.\nlibrary MerkleTree {\n    /// @dev For root calculation we need at least one empty leaf, thus the minus one in the formula.\n    uint256 internal constant MAX_LEAVES = 2 ** ORIGIN_TREE_HEIGHT - 1;\n\n    // ═════════════════════════════════════════════════ BASE TREE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Inserts `node` into merkle tree\n     * @dev Reverts if tree is full\n     * @param newCount  Amount of inserted leaves in the tree after the insertion (i.e. current + 1)\n     * @param node      Element to insert into tree\n     */\n    function insertBase(BaseTree storage tree, uint256 newCount, bytes32 node) internal {\n        if (newCount \u003e MAX_LEAVES) revert MerkleTreeFull();\n        // We go up the tree following the branch from the empty leaf AFTER the just inserted one.\n        // We stop when we find the first \"right child\" node.\n        // Its sibling is now the rightmost \"left child\" node that has two non-empty children.\n        // Therefore we need to update `tree.branch` value on this level.\n        // One could see that `tree.branch` value on lower and higher levels remain unchanged.\n\n        // Loop invariant: `node` is the current level's value for the branch from JUST INSERTED leaf\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            if ((newCount \u0026 1) == 1) {\n                // Found the first \"right child\" node on the branch from EMPTY leaf\n                // `node` is the value for node on branch from JUST INSERTED leaf\n                // Which in this case is the \"left child\".\n                // We update tree.branch and exit\n                tree.branch[i] = node;\n                return;\n            }\n            // On the branch from EMPTY leaf this is still a \"left child\".\n            // Meaning on branch from JUST INSERTED leaf, `node` is a right child.\n            // We compute value for `node` parent using `tree.branch` invariant:\n            // This is the rightmost \"left child\" node, which would be sibling of `node`.\n            node = MerkleMath.getParent(tree.branch[i], node);\n            // Get the parent index, and go to the next tree level\n            newCount \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n        // As the loop should always end prematurely with the `return` statement,\n        // this code should be unreachable. We assert `false` just to be safe.\n        assert(false);\n    }\n\n    /**\n     * @notice Calculates and returns current root of the merkle tree.\n     * @param count     Current amount of inserted leaves in the tree\n     * @return current  Calculated root of `tree`\n     */\n    function rootBase(BaseTree storage tree, uint256 count) internal view returns (bytes32 current) {\n        // To calculate the root we follow the branch of first EMPTY leaf (index == count)\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            // Check if we are the left or the right child on the current level\n            if ((count \u0026 1) == 1) {\n                // We are the right child. Our sibling is the \"rightmost\" \"left-child\" node\n                // that has two non-empty children → sibling is `tree.branch[i]`\n                current = MerkleMath.getParent(tree.branch[i], current);\n            } else {\n                // We are the left child. Our sibling does not exist yet → sibling is EMPTY\n                current = MerkleMath.getParent(current, bytes32(0));\n            }\n            // Get the parent index, and go to the next tree level\n            count \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    // ══════════════════════════════════════════════ HISTORICAL TREE ══════════════════════════════════════════════════\n\n    /// @notice Initializes the historical roots for the tree by inserting an empty root.\n    // solhint-disable-next-line ordering\n    function initializeRoots(HistoricalTree storage tree) internal returns (bytes32 savedRoot) {\n        // This should only be called once, when the contract is initialized\n        assert(tree.roots.length == 0);\n        // Save root for empty merkle tree: bytes32(0)\n        tree.roots.push(savedRoot);\n    }\n\n    /// @notice Inserts a new leaf into the merkle tree.\n    /// @dev Reverts if tree is full.\n    /// @param node         Element to insert into tree\n    /// @return newRoot     Merkle root after the leaf was inserted\n    function insert(HistoricalTree storage tree, bytes32 node) internal returns (bytes32 newRoot) {\n        // Tree count after the new leaf will be inserted (we store roots[0] as root of empty tree)\n        uint256 newCount = tree.roots.length;\n        tree.tree.insertBase(newCount, node);\n        // Save the new root\n        newRoot = tree.tree.rootBase(newCount);\n        tree.roots.push(newRoot);\n    }\n\n    /// @notice Returns the historical root of the merkle tree.\n    /// @dev Reverts if not enough leafs have been inserted.\n    /// @param count            Amount of leafs in the tree at some point of time\n    /// @return historicalRoot  Merkle root after `count` leafs were inserted\n    function root(HistoricalTree storage tree, uint256 count) internal view returns (bytes32 historicalRoot) {\n        if (count \u003e= tree.roots.length) revert NotEnoughLeafs();\n        return tree.roots[count];\n    }\n\n    // ═══════════════════════════════════════════════ DYNAMIC TREE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Updates the value for the leaf with the given index in the Dynamic Merkle Tree.\n     * @dev Will revert if incorrect proof of inclusion for old value is supplied.\n     * @param tree          Dynamic merkle tree\n     * @param index         Index of the leaf to update\n     * @param oldValue      Previous value of the leaf\n     * @param branch        Proof of inclusion of previous value into the tree\n     * @param newValue      New leaf value to assign\n     * @return newRoot      New value for the Merkle Root after the leaf is updated\n     */\n    function update(\n        DynamicTree storage tree,\n        uint256 index,\n        bytes32 oldValue,\n        bytes32[] memory branch,\n        bytes32 newValue\n    ) internal returns (bytes32 newRoot) {\n        // Check that the old value + proof result in a correct root\n        if (MerkleMath.proofRoot(index, oldValue, branch, AGENT_TREE_HEIGHT) != tree.root) {\n            revert LeafNotProven();\n        }\n        // New root is new value + the same proof (values for sibling nodes are not updated)\n        newRoot = MerkleMath.proofRoot(index, newValue, branch, AGENT_TREE_HEIGHT);\n        // Write the new root\n        tree.root = newRoot;\n    }\n}\n\n// contracts/libs/stack/Tips.sol\n\n/// Tips is encoded data with \"tips paid for sending a base message\".\n/// Note: even though uint256 is also an underlying type for MemView, Tips is stored ON STACK.\ntype Tips is uint256;\n\nusing TipsLib for Tips global;\n\n/// # Tips\n/// Library for formatting _the tips part_ of _the base messages_.\n///\n/// ## How the tips are awarded\n/// Tips are paid for sending a base message, and are split across all the agents that\n/// made the message execution on destination chain possible.\n/// ### Summit tips\n/// Split between:\n///     - Guard posting a snapshot with state ST_G for the origin chain.\n///     - Notary posting a snapshot SN_N using ST_G. This creates attestation A.\n///     - Notary posting a message receipt after it is executed on destination chain.\n/// ### Attestation tips\n/// Paid to:\n///     - Notary posting attestation A to destination chain.\n/// ### Execution tips\n/// Paid to:\n///     - First executor performing a valid execution attempt (correct proofs, optimistic period over),\n///      using attestation A to prove message inclusion on origin chain, whether the recipient reverted or not.\n/// ### Delivery tips.\n/// Paid to:\n///     - Executor who successfully executed the message on destination chain.\n///\n/// ## Tips encoding\n/// - Tips occupy a single storage word, and thus are stored on stack instead of being stored in memory.\n/// - The actual tip values should be determined by multiplying stored values by divided by TIPS_MULTIPLIER=2**32.\n/// - Tips are packed into a single word of storage, while allowing real values up to ~8*10**28 for every tip category.\n/// \u003e The only downside is that the \"real tip values\" are now multiplies of ~4*10**9, which should be fine even for\n/// the chains with the most expensive gas currency.\n/// # Tips stack layout (from highest bits to lowest)\n///\n/// | Position   | Field          | Type   | Bytes | Description                                                |\n/// | ---------- | -------------- | ------ | ----- | ---------------------------------------------------------- |\n/// | (032..024] | summitTip      | uint64 | 8     | Tip for agents interacting with Summit contract            |\n/// | (024..016] | attestationTip | uint64 | 8     | Tip for Notary posting attestation to Destination contract |\n/// | (016..008] | executionTip   | uint64 | 8     | Tip for valid execution attempt on destination chain       |\n/// | (008..000] | deliveryTip    | uint64 | 8     | Tip for successful message delivery on destination chain   |\n\nlibrary TipsLib {\n    using SafeCast for uint256;\n\n    /// @dev Amount of bits to shift to summitTip field\n    uint256 private constant SHIFT_SUMMIT_TIP = 24 * 8;\n    /// @dev Amount of bits to shift to attestationTip field\n    uint256 private constant SHIFT_ATTESTATION_TIP = 16 * 8;\n    /// @dev Amount of bits to shift to executionTip field\n    uint256 private constant SHIFT_EXECUTION_TIP = 8 * 8;\n\n    // ═══════════════════════════════════════════════════ TIPS ════════════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips with the given fields\n    /// @param summitTip_        Tip for agents interacting with Summit contract, divided by TIPS_MULTIPLIER\n    /// @param attestationTip_   Tip for Notary posting attestation to Destination contract, divided by TIPS_MULTIPLIER\n    /// @param executionTip_     Tip for valid execution attempt on destination chain, divided by TIPS_MULTIPLIER\n    /// @param deliveryTip_      Tip for successful message delivery on destination chain, divided by TIPS_MULTIPLIER\n    function encodeTips(uint64 summitTip_, uint64 attestationTip_, uint64 executionTip_, uint64 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // forgefmt: disable-next-item\n        return Tips.wrap(\n            uint256(summitTip_) \u003c\u003c SHIFT_SUMMIT_TIP |\n            uint256(attestationTip_) \u003c\u003c SHIFT_ATTESTATION_TIP |\n            uint256(executionTip_) \u003c\u003c SHIFT_EXECUTION_TIP |\n            uint256(deliveryTip_)\n        );\n    }\n\n    /// @notice Convenience function to encode tips with uint256 values.\n    function encodeTips256(uint256 summitTip_, uint256 attestationTip_, uint256 executionTip_, uint256 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // In practice, the tips amounts are not supposed to be higher than 2**96, and with 32 bits of granularity\n        // using uint64 is enough to store the values. However, we still check for overflow just in case.\n        // TODO: consider using Number type to store the tips values.\n        return encodeTips({\n            summitTip_: (summitTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            attestationTip_: (attestationTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            executionTip_: (executionTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            deliveryTip_: (deliveryTip_ \u003e\u003e TIPS_GRANULARITY).toUint64()\n        });\n    }\n\n    /// @notice Wraps the padded encoded tips into a Tips-typed value.\n    /// @dev There is no actual padding here, as the underlying type is already uint256,\n    /// but we include this function for consistency and to be future-proof, if tips will eventually use anything\n    /// smaller than uint256.\n    function wrapPadded(uint256 paddedTips) internal pure returns (Tips) {\n        return Tips.wrap(paddedTips);\n    }\n\n    /**\n     * @notice Returns a formatted Tips payload specifying empty tips.\n     * @return Formatted tips\n     */\n    function emptyTips() internal pure returns (Tips) {\n        return Tips.wrap(0);\n    }\n\n    /// @notice Returns tips's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Tips tips) internal pure returns (bytes32 hashedTips) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store tips in scratch space\n            mstore(0, tips)\n            // Compute hash of tips padded to 32 bytes\n            hashedTips := keccak256(0, 32)\n        }\n    }\n\n    // ═══════════════════════════════════════════════ TIPS SLICING ════════════════════════════════════════════════════\n\n    /// @notice Returns summitTip field\n    function summitTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_SUMMIT_TIP);\n    }\n\n    /// @notice Returns attestationTip field\n    function attestationTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_ATTESTATION_TIP);\n    }\n\n    /// @notice Returns executionTip field\n    function executionTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_EXECUTION_TIP);\n    }\n\n    /// @notice Returns deliveryTip field\n    function deliveryTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips));\n    }\n\n    // ════════════════════════════════════════════════ TIPS VALUE ═════════════════════════════════════════════════════\n\n    /// @notice Returns total value of the tips payload.\n    /// This is the sum of the encoded values, scaled up by TIPS_MULTIPLIER\n    function value(Tips tips) internal pure returns (uint256 value_) {\n        value_ = uint256(tips.summitTip()) + tips.attestationTip() + tips.executionTip() + tips.deliveryTip();\n        value_ \u003c\u003c= TIPS_GRANULARITY;\n    }\n\n    /// @notice Increases the delivery tip to match the new value.\n    function matchValue(Tips tips, uint256 newValue) internal pure returns (Tips newTips) {\n        uint256 oldValue = tips.value();\n        if (newValue \u003c oldValue) revert TipsValueTooLow();\n        // We want to increase the delivery tip, while keeping the other tips the same\n        unchecked {\n            uint256 delta = (newValue - oldValue) \u003e\u003e TIPS_GRANULARITY;\n            // `delta` fits into uint224, as TIPS_GRANULARITY is 32, so this never overflows uint256.\n            // In practice, this will never overflow uint64 as well, but we still check it just in case.\n            if (delta + tips.deliveryTip() \u003e type(uint64).max) revert TipsOverflow();\n            // Delivery tips occupy lowest 8 bytes, so we can just add delta to the tips value\n            // to effectively increase the delivery tip (knowing that delta fits into uint64).\n            newTips = Tips.wrap(Tips.unwrap(tips) + delta);\n        }\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    function __Ownable_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable_init_unchained() internal onlyInitializing {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n    function __Ownable2Step_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable2Step_init_unchained() internal onlyInitializing {\n    }\n    address private _pendingOwner;\n\n    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Returns the address of the pending owner.\n     */\n    function pendingOwner() public view virtual returns (address) {\n        return _pendingOwner;\n    }\n\n    /**\n     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual override onlyOwner {\n        _pendingOwner = newOwner;\n        emit OwnershipTransferStarted(owner(), newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual override {\n        delete _pendingOwner;\n        super._transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev The new owner accepts the ownership transfer.\n     */\n    function acceptOwnership() public virtual {\n        address sender = _msgSender();\n        require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n        _transferOwnership(sender);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// contracts/libs/memory/State.sol\n\n/// State is a memory view over a formatted state payload.\ntype State is uint256;\n\nusing StateLib for State global;\n\n/// # State\n/// State structure represents the state of Origin contract at some point of time.\n/// - State is structured in a way to track the updates of the Origin Merkle Tree.\n/// - State includes root of the Origin Merkle Tree, origin domain and some additional metadata.\n/// ## Origin Merkle Tree\n/// Hash of every sent message is inserted in the Origin Merkle Tree, which changes\n/// the value of Origin Merkle Root (which is the root for the mentioned tree).\n/// - Origin has a single Merkle Tree for all messages, regardless of their destination domain.\n/// - This leads to Origin state being updated if and only if a message was sent in a block.\n/// - Origin contract is a \"source of truth\" for states: a state is considered \"valid\" in its Origin,\n/// if it matches the state of the Origin contract after the N-th (nonce) message was sent.\n///\n/// # Memory layout of State fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                    |\n/// | ---------- | ----------- | ------- | ----- | ------------------------------ |\n/// | [000..032) | root        | bytes32 | 32    | Root of the Origin Merkle Tree |\n/// | [032..036) | origin      | uint32  | 4     | Domain where Origin is located |\n/// | [036..040) | nonce       | uint32  | 4     | Amount of sent messages        |\n/// | [040..045) | blockNumber | uint40  | 5     | Block of last sent message     |\n/// | [045..050) | timestamp   | uint40  | 5     | Time of last sent message      |\n/// | [050..062) | gasData     | uint96  | 12    | Gas data for the chain         |\n///\n/// @dev State could be used to form a Snapshot to be signed by a Guard or a Notary.\nlibrary StateLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_ROOT = 0;\n    uint256 private constant OFFSET_ORIGIN = 32;\n    uint256 private constant OFFSET_NONCE = 36;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 40;\n    uint256 private constant OFFSET_TIMESTAMP = 45;\n    uint256 private constant OFFSET_GAS_DATA = 50;\n\n    // ═══════════════════════════════════════════════════ STATE ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted State payload with provided fields\n     * @param root_         New merkle root\n     * @param origin_       Domain of Origin's chain\n     * @param nonce_        Nonce of the merkle root\n     * @param blockNumber_  Block number when root was saved in Origin\n     * @param timestamp_    Block timestamp when root was saved in Origin\n     * @param gasData_      Gas data for the chain\n     * @return Formatted state\n     */\n    function formatState(\n        bytes32 root_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_,\n        GasData gasData_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(root_, origin_, nonce_, blockNumber_, timestamp_, gasData_);\n    }\n\n    /**\n     * @notice Returns a State view over the given payload.\n     * @dev Will revert if the payload is not a state.\n     */\n    function castToState(bytes memory payload) internal pure returns (State) {\n        return castToState(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a State view.\n     * @dev Will revert if the memory view is not over a state.\n     */\n    function castToState(MemView memView) internal pure returns (State) {\n        if (!isState(memView)) revert UnformattedState();\n        return State.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted State.\n    function isState(MemView memView) internal pure returns (bool) {\n        return memView.len() == STATE_LENGTH;\n    }\n\n    /// @notice Returns the hash of a State, that could be later signed by a Guard to signal\n    /// that the state is invalid.\n    function hashInvalid(State state) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(stateInvalidSalt, keccak(state))\n        return state.unwrap().keccakSalted(STATE_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(State state) internal pure returns (MemView) {\n        return MemView.wrap(State.unwrap(state));\n    }\n\n    /// @notice Compares two State structures.\n    function equals(State a, State b) internal pure returns (bool) {\n        // Length of a State payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═══════════════════════════════════════════════ STATE HASHING ═══════════════════════════════════════════════════\n\n    /// @notice Returns the hash of the State.\n    /// @dev We are using the Merkle Root of a tree with two leafs (see below) as state hash.\n    function leaf(State state) internal pure returns (bytes32) {\n        (bytes32 leftLeaf_, bytes32 rightLeaf_) = state.subLeafs();\n        // Final hash is the parent of these leafs\n        return keccak256(bytes.concat(leftLeaf_, rightLeaf_));\n    }\n\n    /// @notice Returns \"sub-leafs\" of the State. Hash of these \"sub leafs\" is going to be used\n    /// as a \"state leaf\" in the \"Snapshot Merkle Tree\".\n    /// This enables proving that leftLeaf = (root, origin) was a part of the \"Snapshot Merkle Tree\",\n    /// by combining `rightLeaf` with the remainder of the \"Snapshot Merkle Proof\".\n    function subLeafs(State state) internal pure returns (bytes32 leftLeaf_, bytes32 rightLeaf_) {\n        MemView memView = state.unwrap();\n        // Left leaf is (root, origin)\n        leftLeaf_ = memView.prefix({len_: OFFSET_NONCE}).keccak();\n        // Right leaf is (metadata), or (nonce, blockNumber, timestamp)\n        rightLeaf_ = memView.sliceFrom({index_: OFFSET_NONCE}).keccak();\n    }\n\n    /// @notice Returns the left \"sub-leaf\" of the State.\n    function leftLeaf(bytes32 root_, uint32 origin_) internal pure returns (bytes32) {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(root_, origin_));\n    }\n\n    /// @notice Returns the right \"sub-leaf\" of the State.\n    function rightLeaf(uint32 nonce_, uint40 blockNumber_, uint40 timestamp_, GasData gasData_)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(nonce_, blockNumber_, timestamp_, gasData_));\n    }\n\n    // ═══════════════════════════════════════════════ STATE SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns a historical Merkle root from the Origin contract.\n    function root(State state) internal pure returns (bytes32) {\n        return state.unwrap().index({index_: OFFSET_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns domain of chain where the Origin contract is deployed.\n    function origin(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns nonce of Origin contract at the time, when `root` was the Merkle root.\n    function nonce(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when `root` was saved in Origin.\n    function blockNumber(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when `root` was saved in Origin.\n    /// @dev This is the timestamp according to the origin chain.\n    function timestamp(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n\n    /// @notice Returns gas data for the chain.\n    function gasData(State state) internal pure returns (GasData) {\n        return GasDataLib.wrapGasData(state.unwrap().indexUint({index_: OFFSET_GAS_DATA, bytes_: GAS_DATA_LENGTH}));\n    }\n}\n\n// contracts/libs/memory/BaseMessage.sol\n\n/// BaseMessage is a memory view over the base message supported by Origin-Destination\ntype BaseMessage is uint256;\n\nusing BaseMessageLib for BaseMessage global;\n\n/// BaseMessage structure represents a base message sent via the Origin-Destination contracts.\n/// - It only contains data relevant to the base message, the rest of data is encoded in the message header.\n/// - `sender` and `recipient` for EVM chains are EVM addresses casted to bytes32, while preserving left-alignment.\n/// - `tips` and `request` parameters are specified by a message sender\n/// \u003e Origin will calculate minimum tips for given request and content length, and will reject messages with tips\n/// lower than that.\n///\n/// # Memory layout of BaseMessage fields\n///\n/// | Position   | Field     | Type    | Bytes | Description                            |\n/// | ---------- | --------- | ------- | ----- | -------------------------------------- |\n/// | [000..032) | tips      | uint256 | 32    | Encoded tips paid on origin chain      |\n/// | [032..064) | sender    | bytes32 | 32    | Sender address on origin chain         |\n/// | [064..096) | recipient | bytes32 | 32    | Recipient address on destination chain |\n/// | [096..116) | request   | uint160 | 20    | Encoded request for message execution  |\n/// | [104..AAA) | content   | bytes   | ??    | Content to be passed to recipient      |\nlibrary BaseMessageLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_TIPS = 0;\n    uint256 private constant OFFSET_SENDER = 32;\n    uint256 private constant OFFSET_RECIPIENT = 64;\n    uint256 private constant OFFSET_REQUEST = OFFSET_RECIPIENT + TIPS_LENGTH;\n    uint256 private constant OFFSET_CONTENT = OFFSET_REQUEST + REQUEST_LENGTH;\n\n    // ═══════════════════════════════════════════════ BASE MESSAGE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted BaseMessage payload with provided fields.\n     * @param tips_         Encoded tips information\n     * @param sender_       Sender address on origin chain\n     * @param recipient_    Recipient address on destination chain\n     * @param request_      Encoded request for message execution\n     * @param content_      Raw content to be passed to recipient on destination chain\n     * @return Formatted base message\n     */\n    function formatBaseMessage(Tips tips_, bytes32 sender_, bytes32 recipient_, Request request_, bytes memory content_)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return abi.encodePacked(tips_, sender_, recipient_, request_, content_);\n    }\n\n    /**\n     * @notice Returns a BaseMessage view over the given payload.\n     * @dev Will revert if the payload is not a base message.\n     */\n    function castToBaseMessage(bytes memory payload) internal pure returns (BaseMessage) {\n        return castToBaseMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a BaseMessage view.\n     * @dev Will revert if the memory view is not over a base message payload.\n     */\n    function castToBaseMessage(MemView memView) internal pure returns (BaseMessage) {\n        if (!isBaseMessage(memView)) revert UnformattedBaseMessage();\n        return BaseMessage.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted BaseMessage.\n    function isBaseMessage(MemView memView) internal pure returns (bool) {\n        // Check if sender, recipient, tips fields exist\n        return (memView.len() \u003e= OFFSET_CONTENT);\n        // Content could be empty, so we don't check that\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(BaseMessage baseMessage) internal pure returns (MemView) {\n        return MemView.wrap(BaseMessage.unwrap(baseMessage));\n    }\n\n    /// @notice Returns baseMessage's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        // We hash \"tips\" and \"everything but tips\" to make tips proofs easier to verify\n        return MerkleMath.getParent(baseMessage.tips().leaf(), baseMessage.bodyLeaf());\n    }\n\n    /// @notice Returns hash for the \"everything but tips\" part of the base message.\n    function bodyLeaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_SENDER}).keccak();\n    }\n\n    // ═══════════════════════════════════════════ BASE MESSAGE SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips paid on origin chain.\n    function tips(BaseMessage baseMessage) internal pure returns (Tips) {\n        return TipsLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_TIPS, bytes_: TIPS_LENGTH})));\n    }\n\n    /// @notice Returns sender address on origin chain.\n    function sender(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_SENDER, bytes_: 32});\n    }\n\n    /// @notice Returns recipient address on destination chain.\n    function recipient(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_RECIPIENT, bytes_: 32});\n    }\n\n    /// @notice Returns an encoded request for message execution on destination chain.\n    function request(BaseMessage baseMessage) internal pure returns (Request) {\n        return RequestLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_REQUEST, bytes_: REQUEST_LENGTH})));\n    }\n\n    /// @notice Returns an untyped memory view over the content to be passed to recipient.\n    function content(BaseMessage baseMessage) internal pure returns (MemView) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_CONTENT});\n    }\n}\n\n// contracts/base/MessagingBase.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for all messaging contracts.\n * - Provides context on the local chain's domain.\n * - Provides ownership functionality.\n * - Will be providing pausing functionality when it is implemented.\n */\nabstract contract MessagingBase is MultiCallable, Versioned, Ownable2StepUpgradeable {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @notice Domain of the local chain, set once upon contract creation\n    uint32 public immutable localDomain;\n    // @notice Domain of the Synapse chain, set once upon contract creation\n    uint32 public immutable synapseDomain;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev gap for upgrade safety\n    uint256[50] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    constructor(string memory version_, uint32 synapseDomain_) Versioned(version_) {\n        localDomain = ChainContext.chainId();\n        synapseDomain = synapseDomain_;\n    }\n\n    // TODO: Implement pausing\n\n    /**\n     * @dev Should be impossible to renounce ownership;\n     * we override OpenZeppelin OwnableUpgradeable's\n     * implementation of renounceOwnership to make it a no-op\n     */\n    function renounceOwnership() public override onlyOwner {} //solhint-disable-line no-empty-blocks\n}\n\n// contracts/libs/memory/Message.sol\n\n/// Message is a memory over over a formatted message payload.\ntype Message is uint256;\n\nusing MessageLib for Message global;\n\n/// Library for formatting the various messages supported by Origin and Destination.\n///\n/// # Message memory layout\n///\n/// | Position   | Field  | Type    | Bytes | Description                                             |\n/// | ---------- | ------ | ------- | ----- | ------------------------------------------------------- |\n/// | [000..017) | header | uint136 | 17    | Encoded general routing information for the message     |\n/// | [017..AAA) | body   | bytes   | ??    | Formatted payload (according to flag) with message body |\nlibrary MessageLib {\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MemViewLib for bytes;\n    using HeaderLib for MemView;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_HEADER = 0;\n    uint256 private constant OFFSET_BODY = OFFSET_HEADER + HEADER_LENGTH;\n\n    // ══════════════════════════════════════════════════ MESSAGE ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns formatted message with provided fields.\n     * @param header_   Encoded general routing information for the message\n     * @param body_     Formatted payload (according to flag) with message body\n     * @return Formatted message\n     */\n    function formatMessage(Header header_, bytes memory body_) internal pure returns (bytes memory) {\n        return abi.encodePacked(header_, body_);\n    }\n\n    /**\n     * @notice Returns a Message view over for the given payload.\n     * @dev Will revert if the payload is not a message payload.\n     */\n    function castToMessage(bytes memory payload) internal pure returns (Message) {\n        return castToMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Message view.\n     * @dev Will revert if the memory view is not over a message payload.\n     */\n    function castToMessage(MemView memView) internal pure returns (Message) {\n        if (!isMessage(memView)) revert UnformattedMessage();\n        return Message.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Message.\n     */\n    function isMessage(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Check if headers exist in the payload\n        if (length \u003c OFFSET_BODY) return false;\n        // Check that Header is valid\n        uint256 paddedHeader = _header(memView);\n        if (!HeaderLib.isHeader(paddedHeader)) return false;\n        // Check that body is formatted according to the flag\n        // Only Base/Manager message flags exist\n        if (HeaderLib.wrapPadded(paddedHeader).flag() == MessageFlag.Base) {\n            // Check if body is a formatted base message\n            return _body(memView).isBaseMessage();\n        } else {\n            // Check if body is a formatted calldata for AgentManager call\n            return _body(memView).isCallData();\n        }\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Message message) internal pure returns (MemView) {\n        return MemView.wrap(Message.unwrap(message));\n    }\n\n    /// @notice Returns message's hash: a leaf to be inserted in the Merkle tree.\n    function leaf(Message message) internal pure returns (bytes32) {\n        // We hash header and body separately to make message proofs easier to verify\n        Header header_ = message.header();\n        // Only Base/Manager message flags exist\n        if (header_.flag() == MessageFlag.Base) {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToBaseMessage().leaf());\n        } else {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToCallData().leaf());\n        }\n    }\n\n    // ══════════════════════════════════════════════ MESSAGE SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns message's encoded header field.\n    function header(Message message) internal pure returns (Header) {\n        return HeaderLib.wrapPadded((message.unwrap().indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH})));\n    }\n\n    /// @notice Returns message's body field as an untyped memory view.\n    function body(Message message) internal pure returns (MemView) {\n        MemView memView = message.unwrap();\n        return _body(memView);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns message's padded header without checking that it is a valid header.\n    function _header(MemView memView) private pure returns (uint256) {\n        return memView.indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH});\n    }\n\n    /// @dev Returns an untyped memory view over the body field without checking\n    /// if the whole payload or the body are properly formatted.\n    function _body(MemView memView) private pure returns (MemView) {\n        return memView.sliceFrom({index_: OFFSET_BODY});\n    }\n}\n\n// contracts/base/AgentSecured.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for messaging contracts that are secured by the agent manager.\n * `AgentSecured` relies on `AgentManager` to provide the following functionality:\n * - Keep track of agents and their statuses.\n * - Pass agent-signed statements that were verified by the agent manager.\n * - These statements are considered valid indefinitely, unless the agent is disputed.\n * - Disputes are opened and resolved by the agent manager.\n * \u003e `AgentSecured` implementation should never use statements signed by agents that are disputed.\n */\nabstract contract AgentSecured is MessagingBase, IAgentSecured {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    address public immutable agentManager;\n\n    /// @inheritdoc IAgentSecured\n    address public immutable inbox;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    // (agent index =\u003e their dispute status: flag, openedAt, resolvedAt)\n    mapping(uint32 =\u003e DisputeStatus) internal _disputes;\n\n    /// @dev gap for upgrade safety\n    uint256[49] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    modifier onlyAgentManager() {\n        if (msg.sender != agentManager) revert CallerNotAgentManager();\n        _;\n    }\n\n    modifier onlyInbox() {\n        if (msg.sender != inbox) revert CallerNotInbox();\n        _;\n    }\n\n    constructor(string memory version_, uint32 synapseDomain_, address agentManager_, address inbox_)\n        MessagingBase(version_, synapseDomain_)\n    {\n        agentManager = agentManager_;\n        inbox = inbox_;\n    }\n\n    // ════════════════════════════════════════════ ONLY AGENT MANAGER ═════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external onlyAgentManager {\n        uint40 openedAt = ChainContext.blockTimestamp();\n        DisputeStatus memory status = DisputeStatus({flag: DisputeFlag.Pending, openedAt: openedAt, resolvedAt: 0});\n        _disputes[guardIndex] = status;\n        _disputes[notaryIndex] = status;\n    }\n\n    /// @inheritdoc IAgentSecured\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external onlyAgentManager {\n        // Update the dispute status of the slashed agent first.\n        uint40 resolvedAt = ChainContext.blockTimestamp();\n        _disputes[slashedIndex].flag = DisputeFlag.Slashed;\n        _disputes[slashedIndex].resolvedAt = resolvedAt;\n        // Mark the rival agent as not disputed, if there was an ongoing dispute.\n        if (rivalIndex != 0) {\n            _disputes[rivalIndex].flag = DisputeFlag.None;\n            _disputes[rivalIndex].resolvedAt = resolvedAt;\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function agentStatus(address agent) external view returns (AgentStatus memory) {\n        return _agentStatus(agent);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status) {\n        return _getAgent(index);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory) {\n        return _disputes[agentIndex];\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns status of the given agent: (flag, domain, index).\n    function _agentStatus(address agent) internal view returns (AgentStatus memory) {\n        return IAgentManager(agentManager).agentStatus(agent);\n    }\n\n    /// @dev Returns agent and their status for a given agent index. Returns zero values for non existing indexes.\n    function _getAgent(uint256 index) internal view returns (address agent, AgentStatus memory status) {\n        return IAgentManager(agentManager).getAgent(index);\n    }\n\n    /// @dev Checks if a Dispute exists for the given Notary. This function returns true, if\n    /// Notary is in ongoing Dispute, or if Dispute was resolved not in Notary's favor.\n    /// In both cases we can't trust Notary's data.\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeExists(uint32 notaryIndex) internal view returns (bool) {\n        return _disputes[notaryIndex].flag != DisputeFlag.None;\n    }\n\n    /// @dev Checks if a Notary recently won a Dispute and is still in the \"post-dispute\" timeout period.\n    /// In this period we still can't trust Notary's data, though we can optimistically assume that\n    /// that the data will be correct after the timeout (assuming no new Disputes are opened).\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeTimeout(uint32 notaryIndex) internal view returns (bool) {\n        DisputeStatus memory status = _disputes[notaryIndex];\n        // Exit early if Notary is in ongoing Dispute / slashed.\n        if (status.flag != DisputeFlag.None) return false;\n        // Check if Notary has been in any Dispute at all.\n        if (status.openedAt == 0) return false;\n        // Otherwise check if the Dispute timeout is still active.\n        return block.timestamp \u003c status.resolvedAt + DISPUTE_TIMEOUT_NOTARY;\n    }\n}\n\n// contracts/hubs/StateHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StateHub` is a parent contract for `Origin`. It is responsible for the following:\n/// - Keeping track of the historical Origin Merkle Tree containing all the message hashes.\n/// - Keeping track of the historical Origin States, as well as verifying their validity.\nabstract contract StateHub is AgentSecured, StateHubEvents, IStateHub {\n    using SafeCast for uint256;\n    using StateLib for bytes;\n\n    struct OriginState {\n        uint40 blockNumber;\n        uint40 timestamp;\n        GasData gasData;\n    }\n    // Bits left for tight packing: 80\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Historical Merkle Tree\n    /// Note: Takes two storage slots\n    HistoricalTree private _tree;\n\n    /// @dev All historical contract States\n    OriginState[] private _originStates;\n\n    /// @dev gap for upgrade safety\n    uint256[47] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IStateHub\n    function isValidState(bytes memory statePayload) external view returns (bool isValid) {\n        // This will revert if payload is not a formatted state\n        State state = statePayload.castToState();\n        return _isValidState(state);\n    }\n\n    /// @inheritdoc IStateHub\n    function statesAmount() external view returns (uint256) {\n        return _originStates.length;\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestLatestState() external view returns (bytes memory stateData) {\n        // This never underflows, assuming the contract was initialized\n        return suggestState(_nextNonce() - 1);\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestState(uint32 nonce) public view returns (bytes memory stateData) {\n        // This will revert if nonce is out of range\n        bytes32 root = _tree.root(nonce);\n        return _formatOriginState(_originStates[nonce], root, localDomain, nonce);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Initializes the saved states list by inserting a state for an empty Merkle Tree.\n    function _initializeStates() internal {\n        // This should only be called once, when the contract is initialized\n        // This will revert if _tree.roots is non-empty\n        bytes32 savedRoot = _tree.initializeRoots();\n        // Save root for empty merkle _tree with block number and timestamp of initialization\n        _saveState(savedRoot, _toOriginState());\n    }\n\n    /// @dev Inserts leaf into the Merkle Tree and saves the updated origin State.\n    function _insertAndSave(bytes32 leaf) internal {\n        bytes32 newRoot = _tree.insert(leaf);\n        _saveState(newRoot, _toOriginState());\n    }\n\n    /// @dev Saves an updated state of the Origin contract\n    function _saveState(bytes32 root, OriginState memory state) internal {\n        uint32 nonce = _nextNonce();\n        _originStates.push(state);\n        // Emit event with raw state data\n        emit StateSaved(_formatOriginState(state, root, localDomain, nonce));\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns nonce of the next sent message: the amount of saved States so far.\n    /// This always equals to \"total amount of sent messages\" plus 1.\n    function _nextNonce() internal view returns (uint32) {\n        // TODO: consider using more than 32 bits for origin nonces\n        return _originStates.length.toUint32();\n    }\n\n    /// @dev Checks if a state is valid, i.e. if it matches the historical one.\n    /// Reverts, if state refers to another Origin contract.\n    function _isValidState(State state) internal view returns (bool) {\n        // Check if state refers to this contract\n        if (state.origin() != localDomain) revert IncorrectOriginDomain();\n        // Check if nonce exists\n        uint32 nonce = state.nonce();\n        if (nonce \u003e= _originStates.length) return false;\n        // Check if state root matches the historical one\n        if (state.root() != _tree.root(nonce)) return false;\n        // Check if state metadata matches the historical one\n        return _areEqual(state, _originStates[nonce]);\n    }\n\n    // ═════════════════════════════════════════════ STRUCT FORMATTING ═════════════════════════════════════════════════\n\n    /// @dev Returns a formatted payload for a stored OriginState.\n    function _formatOriginState(OriginState memory originState, bytes32 root, uint32 origin, uint32 nonce)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return StateLib.formatState({\n            root_: root,\n            origin_: origin,\n            nonce_: nonce,\n            blockNumber_: originState.blockNumber,\n            timestamp_: originState.timestamp,\n            gasData_: originState.gasData\n        });\n    }\n\n    /// @dev Child contract should implement the logic for getting the current gas data from the gas oracle\n    /// to be saved as part of the Origin State.\n    // solhint-disable-next-line ordering\n    function _fetchGasData() internal view virtual returns (GasData);\n\n    /// @dev Returns a OriginState struct to save in the contract.\n    function _toOriginState() internal view returns (OriginState memory originState) {\n        originState.blockNumber = ChainContext.blockNumber();\n        originState.timestamp = ChainContext.blockTimestamp();\n        originState.gasData = _fetchGasData();\n    }\n\n    /// @dev Checks that a state and its Origin representation are equal.\n    function _areEqual(State state, OriginState memory originState) internal pure returns (bool) {\n        return state.blockNumber() == originState.blockNumber \u0026\u0026 state.timestamp() == originState.timestamp;\n    }\n}\n\n// contracts/Origin.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Origin` contract is used for sending messages to remote chains. It is done\n/// by inserting the message hashes into the Origin Merkle, which makes it possible to\n/// prove that message was sent using the Merkle proof against the Origin Merkle Root. This essentially\n/// compresses the list of messages into a single 32-byte value that needs to be stored on the destination chain.\n/// `Origin` is responsible for the following:\n/// - Formatting the sent message payloads, and inserting their hashes into the Origin Merkle Tree.\n/// - Keeping track of its own historical states (see parent contract `StateHub`).\n/// - Enforcing minimum tip values for sent base messages based on the provided execution requests.\n/// - Distributing the collected tips upon request from a local `AgentManager` contract.\ncontract Origin is StateHub, OriginEvents, InterfaceOrigin {\n    using MemViewLib for bytes;\n    using MessageLib for bytes;\n    using TipsLib for bytes;\n    using TypeCasts for address;\n\n    address public immutable gasOracle;\n\n    modifier onlyRemoteDestination(uint32 destination) {\n        if (destination == localDomain) revert IncorrectDestinationDomain();\n        _;\n    }\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_, address gasOracle_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {\n        gasOracle = gasOracle_;\n    }\n\n    /// @notice Initializes Origin contract:\n    /// - msg.sender is set as contract owner\n    /// - State of \"empty merkle tree\" is saved\n    function initialize() external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize \"states\": state of an \"empty merkle tree\" is saved\n        _initializeStates();\n    }\n\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable onlyRemoteDestination(destination) returns (uint32 messageNonce, bytes32 messageHash) {\n        // Check that content is not too large\n        if (content.length \u003e MAX_CONTENT_BYTES) revert ContentLengthTooBig();\n        // This will revert if msg.value is lower than value of minimum tips\n        Tips tips = _getMinimumTips(destination, paddedRequest, content.length).matchValue(msg.value);\n        Request request = RequestLib.wrapPadded(paddedRequest);\n        // Format the BaseMessage body\n        bytes memory body = BaseMessageLib.formatBaseMessage({\n            sender_: msg.sender.addressToBytes32(),\n            recipient_: recipient,\n            tips_: tips,\n            request_: request,\n            content_: content\n        });\n        // Send the message\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Base, body);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        onlyAgentManager\n        onlyRemoteDestination(destination)\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // AgentManager (checked via modifier) is responsible for constructing the calldata payload correctly.\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Manager, payload);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function withdrawTips(address recipient, uint256 amount) external onlyAgentManager {\n        if (address(this).balance \u003c amount) revert InsufficientEthBalance();\n        (bool success,) = recipient.call{value: amount}(\"\");\n        if (!success) revert EthTransferFailed();\n        emit TipWithdrawalCompleted(recipient, amount);\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue)\n    {\n        return _getMinimumTips(destination, paddedRequest, contentLength).value();\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Sends the given message to the specified destination. Message hash is inserted\n    /// into the Origin Merkle Tree, which will enable message execution on destination chain.\n    function _sendMessage(uint32 destination, uint32 optimisticPeriod, MessageFlag flag, bytes memory body)\n        internal\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // Format the message header\n        messageNonce = _nextNonce();\n        Header header = flag.encodeHeader({\n            origin_: localDomain,\n            nonce_: messageNonce,\n            destination_: destination,\n            optimisticPeriod_: optimisticPeriod\n        });\n        // Format the full message payload\n        bytes memory msgPayload = MessageLib.formatMessage(header, body);\n        // Insert new leaf into the Origin Merkle Tree and save the updated state\n        messageHash = msgPayload.castToMessage().leaf();\n        _insertAndSave(messageHash);\n        // Emit event with message information\n        emit Sent(messageHash, messageNonce, destination, msgPayload);\n        // Update the gas oracle data. We do this after the provided tips are checked so that\n        // the provided message is sent in the event that the gas oracle data is updated to a higher value.\n        InterfaceGasOracle(gasOracle).updateGasData(destination);\n        // TODO: consider doing this before the message is sent, while adjusting GasOracle.getMinimumTips() to\n        // use the pending gas oracle data.\n    }\n\n    /// @dev Returns the minimum tips for sending a message to the given destination with the given request and content.\n    function _getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        internal\n        view\n        returns (Tips)\n    {\n        return\n            TipsLib.wrapPadded(InterfaceGasOracle(gasOracle).getMinimumTips(destination, paddedRequest, contentLength));\n    }\n\n    /// @dev Gets the current gas data from the gas oracle to be saved as part of the Origin State.\n    function _fetchGasData() internal view override returns (GasData) {\n        return GasDataLib.wrapGasData(InterfaceGasOracle(gasOracle).getGasData());\n    }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"80969:1198:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;80969:1198:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"80969:1198:0:-:0;;;;;;;;","abiDefinition":[],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Origin.sol\":\"StructureUtils\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Origin.sol\":{\"keccak256\":\"0x96775924f147f3d1f8df8cdf56731fe52a15af8d8e12e608efb8158c112b18cd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e642a27f5fab3c62b4c02e9754e9e42b1cf2e5381dbea9d3d106d23b7772ebe6\",\"dweb:/ipfs/QmUwn7ZyBvPkjnMuK8ZMSexBUdNQnVtxwyoAyT4DXLQjra\"]}},\"version\":1}"},"hashes":{}},"solidity/Origin.sol:TipsLib":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220c66b602df1d422f0aa4a073f1c2216a4400eb15b6ec8c46036319906ea2ffcbf64736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220c66b602df1d422f0aa4a073f1c2216a4400eb15b6ec8c46036319906ea2ffcbf64736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/OriginEvents.sol\n\n/// @notice A collection of events emitted by the Origin contract\nabstract contract OriginEvents {\n    /**\n     * @notice Emitted when a new message is sent.\n     * @param messageHash   Hash of message; the leaf inserted to the Merkle tree for the message\n     * @param nonce         Nonce of sent message (starts from 1)\n     * @param destination   Destination domain\n     * @param message       Raw bytes of message\n     */\n    event Sent(bytes32 indexed messageHash, uint32 indexed nonce, uint32 indexed destination, bytes message);\n\n    /**\n     * @notice Emitted when a tip withdrawal is completed.\n     * @param actor     Actor address\n     * @param tip       Tip value, denominated in local domain's wei\n     */\n    event TipWithdrawalCompleted(address actor, uint256 tip);\n}\n\n// contracts/events/StateHubEvents.sol\n\n/// @notice A collection of events emitted by the StateHub contract\nabstract contract StateHubEvents {\n    /**\n     * @notice Emitted when a new Origin State is saved after a message was sent.\n     * @param state     Raw payload with state data\n     */\n    event StateSaved(bytes state);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n    /**\n     * @notice Check that a given state is valid: matches the historical state of Origin contract.\n     * Note: any Agent including an invalid state in their snapshot will be slashed\n     * upon providing the snapshot and agent signature for it to Origin contract.\n     * @dev Will revert if any of these is true:\n     *  - State payload is not properly formatted.\n     * @param statePayload      Raw payload with state data\n     * @return isValid          Whether the provided state is valid\n     */\n    function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns the amount of saved states so far.\n     * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n     */\n    function statesAmount() external view returns (uint256);\n\n    /**\n     * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @return statePayload     Raw payload with the latest state data\n     */\n    function suggestLatestState() external view returns (bytes memory statePayload);\n\n    /**\n     * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @param nonce             Historical nonce to form a state\n     * @return statePayload     Raw payload with historical state data\n     */\n    function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/InterfaceGasOracle.sol\n\ninterface InterfaceGasOracle {\n    /**\n     * @notice Fetches the latest gas data for the chain from `Destination` contract,\n     * and uses it to update the oracle values for the requested chain.\n     * @param domain    Domain to update the gas data for\n     */\n    function updateGasData(uint32 domain) external;\n\n    /**\n     * @notice Returns the gas data for the local chain.\n     */\n    function getGasData() external view returns (uint256 paddedGasData);\n\n    /**\n     * @notice Returns the gas data for the given domain, in the decoded format.\n     * @param domain        Domain of chain to get gas data for\n     * @return gasPrice     Gas price for the chain (in Wei per gas unit)\n     * @return dataPrice    Calldata price (in Wei per byte of content)\n     * @return execBuffer   Tx fee safety buffer for message execution (in Wei)\n     * @return amortAttCost Amortized cost for attestation submission (in Wei)\n     * @return etherPrice   Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n     * @return markup       Markup for the message execution (in BWAD)\n     */\n    function getDecodedGasData(uint32 domain)\n        external\n        view\n        returns (\n            uint256 gasPrice,\n            uint256 dataPrice,\n            uint256 execBuffer,\n            uint256 amortAttCost,\n            uint256 etherPrice,\n            uint256 markup\n        );\n\n    /**\n     * @notice Returns the minimum tips for sending a message to a given destination.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return paddedTips       Padded encoded minimum tips information\n     */\n    function getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 paddedTips);\n}\n\n// contracts/interfaces/InterfaceOrigin.sol\n\ninterface InterfaceOrigin {\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /**\n     * @notice Send a message to the recipient located on destination domain.\n     * @dev Recipient has to conform to IMessageRecipient interface, otherwise message won't be delivered.\n     * Will revert if any of these is true:\n     * - `destination` is equal to contract's local domain\n     * - `content` length is greater than `MAX_CONTENT_BYTES`\n     * - `msg.value` is lower than value of minimum tips for the given message\n     * @param destination           Domain of destination chain\n     * @param recipient             Address of recipient on destination chain as bytes32\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param paddedRequest         Padded encoded message execution request on destination chain\n     * @param content               Raw bytes content of message\n     * @return messageNonce         Nonce of the sent message\n     * @return messageHash          Hash of the sent message\n     */\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable returns (uint32 messageNonce, bytes32 messageHash);\n\n    /**\n     * @notice Send a manager message to the destination domain.\n     * @dev This could only be called by AgentManager, which takes care of encoding the calldata payload.\n     * Note: (msgOrigin, proofMaturity) security args will be added to payload on the destination chain\n     * so that the AgentManager could verify where the Manager Message came from and how mature is the proof.\n     * Note: function is not payable, as no tips are required for sending a manager message.\n     * Will revert if `destination` is equal to contract's local domain.\n     * @param destination           Domain of destination chain\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param payload               Payload for calling AgentManager on destination chain (with extra security args)\n     */\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        returns (uint32 messageNonce, bytes32 messageHash);\n\n    // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Withdraws locked base message tips to the recipient.\n     * @dev Could only be called by a local AgentManager.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function withdrawTips(address recipient, uint256 amount) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the minimum tips value for sending a message to a given destination.\n     * @dev Using at least `tipsValue` as `msg.value` for `sendBaseMessage()`\n     * will guarantee that the message will be accepted.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return tipsValue        Minimum tips value for a message to be accepted\n     */\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue);\n}\n\n// contracts/libs/Constants.sol\n\n// Here we define common constants to enable their easier reusing later.\n\n// ══════════════════════════════════ MERKLE ═══════════════════════════════════\n/// @dev Height of the Agent Merkle Tree\nuint256 constant AGENT_TREE_HEIGHT = 32;\n/// @dev Height of the Origin Merkle Tree\nuint256 constant ORIGIN_TREE_HEIGHT = 32;\n/// @dev Height of the Snapshot Merkle Tree. Allows up to 64 leafs, e.g. up to 32 states\nuint256 constant SNAPSHOT_TREE_HEIGHT = 6;\n// ══════════════════════════════════ STRUCTS ══════════════════════════════════\n/// @dev See Attestation.sol: (bytes32,bytes32,uint32,uint40,uint40): 32+32+4+5+5\nuint256 constant ATTESTATION_LENGTH = 78;\n/// @dev See GasData.sol: (uint16,uint16,uint16,uint16,uint16,uint16): 2+2+2+2+2+2\nuint256 constant GAS_DATA_LENGTH = 12;\n/// @dev See Receipt.sol: (uint32,uint32,bytes32,bytes32,uint8,address,address,address): 4+4+32+32+1+20+20+20\nuint256 constant RECEIPT_LENGTH = 133;\n/// @dev See State.sol: (bytes32,uint32,uint32,uint40,uint40,GasData): 32+4+4+5+5+len(GasData)\nuint256 constant STATE_LENGTH = 50 + GAS_DATA_LENGTH;\n/// @dev Maximum amount of states in a single snapshot. Each state produces two leafs in the tree\nuint256 constant SNAPSHOT_MAX_STATES = 1 \u003c\u003c (SNAPSHOT_TREE_HEIGHT - 1);\n// ══════════════════════════════════ MESSAGE ══════════════════════════════════\n/// @dev See Header.sol: (uint8,uint32,uint32,uint32,uint32): 1+4+4+4+4\nuint256 constant HEADER_LENGTH = 17;\n/// @dev See Request.sol: (uint96,uint64,uint32): 12+8+4\nuint256 constant REQUEST_LENGTH = 24;\n/// @dev See Tips.sol: (uint64,uint64,uint64,uint64): 8+8+8+8\nuint256 constant TIPS_LENGTH = 32;\n/// @dev The amount of discarded last bits when encoding tip values\nuint256 constant TIPS_GRANULARITY = 32;\n/// @dev Tip values could be only the multiples of TIPS_MULTIPLIER\nuint256 constant TIPS_MULTIPLIER = 1 \u003c\u003c TIPS_GRANULARITY;\n// ══════════════════════════════ STATEMENT SALTS ══════════════════════════════\n/// @dev Salts for signing various statements\nbytes32 constant ATTESTATION_VALID_SALT = keccak256(\"ATTESTATION_VALID_SALT\");\nbytes32 constant ATTESTATION_INVALID_SALT = keccak256(\"ATTESTATION_INVALID_SALT\");\nbytes32 constant RECEIPT_VALID_SALT = keccak256(\"RECEIPT_VALID_SALT\");\nbytes32 constant RECEIPT_INVALID_SALT = keccak256(\"RECEIPT_INVALID_SALT\");\nbytes32 constant SNAPSHOT_VALID_SALT = keccak256(\"SNAPSHOT_VALID_SALT\");\nbytes32 constant STATE_INVALID_SALT = keccak256(\"STATE_INVALID_SALT\");\n// ═════════════════════════════════ PROTOCOL ══════════════════════════════════\n/// @dev Optimistic period for new agent roots in LightManager\nuint32 constant AGENT_ROOT_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Timeout between the agent root could be proposed and resolved in LightManager\nuint32 constant AGENT_ROOT_PROPOSAL_TIMEOUT = 12 hours;\nuint32 constant BONDING_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Amount of time that the Notary will not be considered active after they won a dispute\nuint32 constant DISPUTE_TIMEOUT_NOTARY = 12 hours;\n/// @dev Amount of time without fresh data from Notaries before contract owner can resolve stuck disputes manually\nuint256 constant FRESH_DATA_TIMEOUT = 4 hours;\n/// @dev Maximum bytes per message = 2 KiB (somewhat arbitrarily set to begin)\nuint256 constant MAX_CONTENT_BYTES = 2 * 2 ** 10;\n/// @dev Maximum value for the summit tip that could be set in GasOracle\nuint256 constant MAX_SUMMIT_TIP = 0.01 ether;\n\n// contracts/libs/Errors.sol\n\n// ══════════════════════════════ INVALID CALLER ═══════════════════════════════\n\nerror CallerNotAgentManager();\nerror CallerNotDestination();\nerror CallerNotInbox();\nerror CallerNotSummit();\n\n// ══════════════════════════════ INCORRECT DATA ═══════════════════════════════\n\nerror IncorrectAttestation();\nerror IncorrectAgentDomain();\nerror IncorrectAgentIndex();\nerror IncorrectAgentProof();\nerror IncorrectAgentRoot();\nerror IncorrectDataHash();\nerror IncorrectDestinationDomain();\nerror IncorrectOriginDomain();\nerror IncorrectSnapshotProof();\nerror IncorrectSnapshotRoot();\nerror IncorrectState();\nerror IncorrectStatesAmount();\nerror IncorrectTipsProof();\nerror IncorrectVersionLength();\n\nerror IncorrectNonce();\nerror IncorrectSender();\nerror IncorrectRecipient();\n\nerror FlagOutOfRange();\nerror IndexOutOfRange();\nerror NonceOutOfRange();\n\nerror OutdatedNonce();\n\nerror UnformattedAttestation();\nerror UnformattedAttestationReport();\nerror UnformattedBaseMessage();\nerror UnformattedCallData();\nerror UnformattedCallDataPrefix();\nerror UnformattedMessage();\nerror UnformattedReceipt();\nerror UnformattedReceiptReport();\nerror UnformattedSignature();\nerror UnformattedSnapshot();\nerror UnformattedState();\nerror UnformattedStateReport();\n\n// ═══════════════════════════════ MERKLE TREES ════════════════════════════════\n\nerror LeafNotProven();\nerror MerkleTreeFull();\nerror NotEnoughLeafs();\nerror TreeHeightTooLow();\n\n// ═════════════════════════════ OPTIMISTIC PERIOD ═════════════════════════════\n\nerror BaseClientOptimisticPeriod();\nerror MessageOptimisticPeriod();\nerror SlashAgentOptimisticPeriod();\nerror WithdrawTipsOptimisticPeriod();\nerror ZeroProofMaturity();\n\n// ═══════════════════════════════ AGENT MANAGER ═══════════════════════════════\n\nerror AgentNotGuard();\nerror AgentNotNotary();\n\nerror AgentCantBeAdded();\nerror AgentNotActive();\nerror AgentNotActiveNorUnstaking();\nerror AgentNotFraudulent();\nerror AgentNotUnstaking();\nerror AgentUnknown();\n\nerror AgentRootNotProposed();\nerror AgentRootTimeoutNotOver();\n\nerror NotStuck();\n\nerror DisputeAlreadyResolved();\nerror DisputeNotOpened();\nerror DisputeTimeoutNotOver();\nerror GuardInDispute();\nerror NotaryInDispute();\n\nerror MustBeSynapseDomain();\nerror SynapseDomainForbidden();\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\nerror AlreadyExecuted();\nerror AlreadyFailed();\nerror DuplicatedSnapshotRoot();\nerror IncorrectMagicValue();\nerror GasLimitTooLow();\nerror GasSuppliedTooLow();\n\n// ══════════════════════════════════ ORIGIN ═══════════════════════════════════\n\nerror ContentLengthTooBig();\nerror EthTransferFailed();\nerror InsufficientEthBalance();\n\n// ════════════════════════════════ GAS ORACLE ═════════════════════════════════\n\nerror LocalGasDataNotSet();\nerror RemoteGasDataNotSet();\n\n// ═══════════════════════════════════ TIPS ════════════════════════════════════\n\nerror SummitTipTooHigh();\nerror TipsClaimMoreThanEarned();\nerror TipsClaimZero();\nerror TipsOverflow();\nerror TipsValueTooLow();\n\n// ════════════════════════════════ MEMORY VIEW ════════════════════════════════\n\nerror IndexedTooMuch();\nerror ViewOverrun();\nerror OccupiedMemory();\nerror UnallocatedMemory();\nerror PrecompileOutOfGas();\n\n// ═════════════════════════════════ MULTICALL ═════════════════════════════════\n\nerror MulticallFailed();\n\n// contracts/libs/TypeCasts.sol\n\nlibrary TypeCasts {\n    // alignment preserving cast\n    function addressToBytes32(address addr) internal pure returns (bytes32) {\n        return bytes32(uint256(uint160(addr)));\n    }\n\n    // alignment preserving cast\n    function bytes32ToAddress(bytes32 buf) internal pure returns (address) {\n        return address(uint160(uint256(buf)));\n    }\n}\n\n// contracts/libs/stack/Number.sol\n\n/// Number is a compact representation of uint256, that is fit into 16 bits\n/// with the maximum relative error under 0.4%.\ntype Number is uint16;\n\nusing NumberLib for Number global;\n\n/// # Number\n/// Library for compact representation of uint256 numbers.\n/// - Number is stored using mantissa and exponent, each occupying 8 bits.\n/// - Numbers under 2**8 are stored as `mantissa` with `exponent = 0xFF`.\n/// - Numbers at least 2**8 are approximated as `(256 + mantissa) \u003c\u003c exponent`\n/// \u003e - `0 \u003c= mantissa \u003c 256`\n/// \u003e - `0 \u003c= exponent \u003c= 247` (`256 * 2**248` doesn't fit into uint256)\n/// # Number stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type  | Bytes |\n/// | ---------- | -------- | ----- | ----- |\n/// | (002..001] | mantissa | uint8 | 1     |\n/// | (001..000] | exponent | uint8 | 1     |\n\nlibrary NumberLib {\n    /// @dev Amount of bits to shift to mantissa field\n    uint16 private constant SHIFT_MANTISSA = 8;\n\n    /// @notice For bwad math (binary wad) we use 2**64 as \"wad\" unit.\n    /// @dev We are using not using 10**18 as wad, because it is not stored precisely in NumberLib.\n    uint256 internal constant BWAD_SHIFT = 64;\n    uint256 internal constant BWAD = 1 \u003c\u003c BWAD_SHIFT;\n    /// @notice ~0.1% in bwad units.\n    uint256 internal constant PER_MILLE_SHIFT = BWAD_SHIFT - 10;\n    uint256 internal constant PER_MILLE = 1 \u003c\u003c PER_MILLE_SHIFT;\n\n    /// @notice Compresses uint256 number into 16 bits.\n    function compress(uint256 value) internal pure returns (Number) {\n        // Find `msb` such as `2**msb \u003c= value \u003c 2**(msb + 1)`\n        uint256 msb = mostSignificantBit(value);\n        // We want to preserve 9 bits of precision.\n        // The highest bit is always 1, so we can skip it.\n        // The remaining 8 highest bits are stored as mantissa.\n        if (msb \u003c 8) {\n            // Value is less than 2**8, so we can use value as mantissa with \"-1\" exponent.\n            return _encode(uint8(value), 0xFF);\n        } else {\n            // We use `msb - 8` as exponent otherwise. Note that `exponent \u003e= 0`.\n            unchecked {\n                uint256 exponent = msb - 8;\n                // Shifting right by `msb-8` bits will shift the \"remaining 8 highest bits\" into the 8 lowest bits.\n                // uint8() will truncate the highest bit.\n                return _encode(uint8(value \u003e\u003e exponent), uint8(exponent));\n            }\n        }\n    }\n\n    /// @notice Decompresses 16 bits number into uint256.\n    /// @dev The outcome is an approximation of the original number: `(value - value / 256) \u003c number \u003c= value`.\n    function decompress(Number number) internal pure returns (uint256 value) {\n        // Isolate 8 highest bits as the mantissa.\n        uint256 mantissa = Number.unwrap(number) \u003e\u003e SHIFT_MANTISSA;\n        // This will truncate the highest bits, leaving only the exponent.\n        uint256 exponent = uint8(Number.unwrap(number));\n        if (exponent == 0xFF) {\n            return mantissa;\n        } else {\n            unchecked {\n                return (256 + mantissa) \u003c\u003c (exponent);\n            }\n        }\n    }\n\n    /// @dev Returns the most significant bit of `x`\n    /// https://solidity-by-example.org/bitwise/\n    function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\n        // To find `msb` we determine it bit by bit, starting from the highest one.\n        // `0 \u003c= msb \u003c= 255`, so we start from the highest bit, 1\u003c\u003c7 == 128.\n        // If `x` is at least 2**128, then the highest bit of `x` is at least 128.\n        // solhint-disable no-inline-assembly\n        assembly {\n            // `f` is set to 1\u003c\u003c7 if `x \u003e= 2**128` and to 0 otherwise.\n            let f := shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\n            // If `x \u003e= 2**128` then set `msb` highest bit to 1 and shift `x` right by 128.\n            // Otherwise, `msb` remains 0 and `x` remains unchanged.\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        // `x` is now at most 2**128 - 1. Continue the same way, the next highest bit is 1\u003c\u003c6 == 64.\n        assembly {\n            // `f` is set to 1\u003c\u003c6 if `x \u003e= 2**64` and to 0 otherwise.\n            let f := shl(6, gt(x, 0xFFFFFFFFFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c5 if `x \u003e= 2**32` and to 0 otherwise.\n            let f := shl(5, gt(x, 0xFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c4 if `x \u003e= 2**16` and to 0 otherwise.\n            let f := shl(4, gt(x, 0xFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c3 if `x \u003e= 2**8` and to 0 otherwise.\n            let f := shl(3, gt(x, 0xFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c2 if `x \u003e= 2**4` and to 0 otherwise.\n            let f := shl(2, gt(x, 0xF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c1 if `x \u003e= 2**2` and to 0 otherwise.\n            let f := shl(1, gt(x, 0x3))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1 if `x \u003e= 2**1` and to 0 otherwise.\n            let f := gt(x, 0x1)\n            msb := or(msb, f)\n        }\n    }\n\n    /// @dev Wraps (mantissa, exponent) pair into Number.\n    function _encode(uint8 mantissa, uint8 exponent) private pure returns (Number) {\n        // Casts below are upcasts, so they are safe.\n        return Number.wrap(uint16(mantissa) \u003c\u003c SHIFT_MANTISSA | uint16(exponent));\n    }\n}\n\n// contracts/libs/stack/Request.sol\n\n/// Request is encoded data with \"message execution request\".\ntype Request is uint192;\n\nusing RequestLib for Request global;\n\n/// Library for formatting _the request part_ of _the base messages_.\n/// - Request represents a message sender requirements for the message execution on the destination chain.\n/// - Request occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n/// \u003e gasDrop field is included for future compatibility and is ignored at the moment.\n///\n/// # Request stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type   | Bytes | Description                                          |\n/// | ---------- | -------- | ------ | ----- | ---------------------------------------------------- |\n/// | (024..012] | gasDrop  | uint96 | 12    | Minimum amount of gas token to drop to the recipient |\n/// | (012..004] | gasLimit | uint64 | 8     | Minimum amount of gas units to supply for execution  |\n/// | (004..000] | version  | uint32 | 4     | Base message version to pass to the recipient        |\n\nlibrary RequestLib {\n    /// @dev Amount of bits to shift to gasDrop field\n    uint192 private constant SHIFT_GAS_DROP = 12 * 8;\n    /// @dev Amount of bits to shift to gasLimit field\n    uint192 private constant SHIFT_GAS_LIMIT = 4 * 8;\n\n    /// @notice Returns an encoded request with the given fields\n    /// @param gasDrop_     Minimum amount of gas token to drop to the recipient (ignored at the moment)\n    /// @param gasLimit_    Minimum amount of gas units to supply for execution\n    /// @param version_     Base message version to pass to the recipient\n    function encodeRequest(uint96 gasDrop_, uint64 gasLimit_, uint32 version_) internal pure returns (Request) {\n        // Casts below are upcasts, so they are safe\n        return Request.wrap(uint192(gasDrop_) \u003c\u003c SHIFT_GAS_DROP | uint192(gasLimit_) \u003c\u003c SHIFT_GAS_LIMIT | version_);\n    }\n\n    /// @notice Wraps the padded encoded request into a Request-typed value.\n    /// @dev The \"padded\" request is simply an encoded request casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded requests\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedRequest) internal pure returns (Request) {\n        // Casting to uint192 will truncate the highest bits, which is the behavior we want\n        return Request.wrap(uint192(paddedRequest));\n    }\n\n    /// @notice Returns the requested of gas token to drop to the recipient.\n    function gasDrop(Request request) internal pure returns (uint96) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return uint96(Request.unwrap(request) \u003e\u003e SHIFT_GAS_DROP);\n    }\n\n    /// @notice Returns the requested minimum amount of gas units to supply for execution.\n    function gasLimit(Request request) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Request.unwrap(request) \u003e\u003e SHIFT_GAS_LIMIT);\n    }\n\n    /// @notice Returns the requested base message version to pass to the recipient.\n    function version(Request request) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Request.unwrap(request));\n    }\n}\n\n// node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        require(value \u003c= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        require(value \u003c= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        require(value \u003c= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value \u003c= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        require(value \u003c= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        require(value \u003c= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        require(value \u003c= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        require(value \u003c= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        require(value \u003c= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        require(value \u003c= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        require(value \u003c= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        require(value \u003c= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        require(value \u003c= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        require(value \u003c= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        require(value \u003c= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value \u003c= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        require(value \u003c= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        require(value \u003c= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        require(value \u003c= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value \u003c= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        require(value \u003c= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        require(value \u003c= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        require(value \u003c= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value \u003c= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        require(value \u003c= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        require(value \u003c= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        require(value \u003c= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value \u003c= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        require(value \u003c= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value \u003c= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value \u003c= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     *\n     * _Available since v3.0._\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value \u003e= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     *\n     * _Available since v3.0._\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value \u003c= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     *\n     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length \u003e 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance \u003e= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance \u003e= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length \u003e 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n\n// contracts/base/MultiCallable.sol\n\n/// @notice Collection of Multicall utilities. Fork of Multicall3:\n/// https://github.com/mds1/multicall/blob/master/src/Multicall3.sol\nabstract contract MultiCallable {\n    struct Call {\n        bool allowFailure;\n        bytes callData;\n    }\n\n    struct Result {\n        bool success;\n        bytes returnData;\n    }\n\n    /// @notice Aggregates a few calls to this contract into one multicall without modifying `msg.sender`.\n    function multicall(Call[] calldata calls) external returns (Result[] memory callResults) {\n        uint256 amount = calls.length;\n        callResults = new Result[](amount);\n        Call calldata call_;\n        for (uint256 i = 0; i \u003c amount;) {\n            call_ = calls[i];\n            Result memory result = callResults[i];\n            // We perform a delegate call to ourselves here. Delegate call does not modify `msg.sender`, so\n            // this will have the same effect as if `msg.sender` performed all the calls themselves one by one.\n            // solhint-disable-next-line avoid-low-level-calls\n            (result.success, result.returnData) = address(this).delegatecall(call_.callData);\n            // solhint-disable-next-line no-inline-assembly\n            assembly {\n                // Revert if the call fails and failure is not allowed\n                // `allowFailure := calldataload(call_)` and `success := mload(result)`\n                if iszero(or(calldataload(call_), mload(result))) {\n                    // Revert with `0x4d6a2328` (function selector for `MulticallFailed()`)\n                    mstore(0x00, 0x4d6a232800000000000000000000000000000000000000000000000000000000)\n                    revert(0x00, 0x04)\n                }\n            }\n            unchecked {\n                ++i;\n            }\n        }\n    }\n}\n\n// contracts/base/Version.sol\n\n/**\n * @title Versioned\n * @notice Version getter for contracts. Doesn't use any storage slots, meaning\n * it will never cause any troubles with the upgradeable contracts. For instance, this contract\n * can be added or removed from the inheritance chain without shifting the storage layout.\n */\nabstract contract Versioned {\n    /**\n     * @notice Struct that is mimicking the storage layout of a string with 32 bytes or less.\n     * Length is limited by 32, so the whole string payload takes two memory words:\n     * @param length    String length\n     * @param data      String characters\n     */\n    struct _ShortString {\n        uint256 length;\n        bytes32 data;\n    }\n\n    /// @dev Length of the \"version string\"\n    uint256 private immutable _length;\n    /// @dev Bytes representation of the \"version string\".\n    /// Strings with length over 32 are not supported!\n    bytes32 private immutable _data;\n\n    constructor(string memory version_) {\n        _length = bytes(version_).length;\n        if (_length \u003e 32) revert IncorrectVersionLength();\n        // bytes32 is left-aligned =\u003e this will store the byte representation of the string\n        // with the trailing zeroes to complete the 32-byte word\n        _data = bytes32(bytes(version_));\n    }\n\n    function version() external view returns (string memory versionString) {\n        // Load the immutable values to form the version string\n        _ShortString memory str = _ShortString(_length, _data);\n        // The only way to do this cast is doing some dirty assembly\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            versionString := str\n        }\n    }\n}\n\n// contracts/libs/ChainContext.sol\n\n/// @notice Library for accessing chain context variables as tightly packed integers.\n/// Messaging contracts should rely on this library for accessing chain context variables\n/// instead of doing the casting themselves.\nlibrary ChainContext {\n    using SafeCast for uint256;\n\n    /// @notice Returns the current block number as uint40.\n    /// @dev Reverts if block number is greater than 40 bits, which is not supposed to happen\n    /// until the block.timestamp overflows (assuming block time is at least 1 second).\n    function blockNumber() internal view returns (uint40) {\n        return block.number.toUint40();\n    }\n\n    /// @notice Returns the current block timestamp as uint40.\n    /// @dev Reverts if block timestamp is greater than 40 bits, which is\n    /// supposed to happen approximately in year 36835.\n    function blockTimestamp() internal view returns (uint40) {\n        return block.timestamp.toUint40();\n    }\n\n    /// @notice Returns the chain id as uint32.\n    /// @dev Reverts if chain id is greater than 32 bits, which is not\n    /// supposed to happen in production.\n    function chainId() internal view returns (uint32) {\n        return block.chainid.toUint32();\n    }\n}\n\n// contracts/libs/Structures.sol\n\n// Here we define common enums and structures to enable their easier reusing later.\n\n// ═══════════════════════════════ AGENT STATUS ════════════════════════════════\n\n/// @dev Potential statuses for the off-chain bonded agent:\n/// - Unknown: never provided a bond =\u003e signature not valid\n/// - Active: has a bond in BondingManager =\u003e signature valid\n/// - Unstaking: has a bond in BondingManager, initiated the unstaking =\u003e signature not valid\n/// - Resting: used to have a bond in BondingManager, successfully unstaked =\u003e signature not valid\n/// - Fraudulent: proven to commit fraud, value in Merkle Tree not updated =\u003e signature not valid\n/// - Slashed: proven to commit fraud, value in Merkle Tree was updated =\u003e signature not valid\n/// Unstaked agent could later be added back to THE SAME domain by staking a bond again.\n/// Honest agent: Unknown -\u003e Active -\u003e unstaking -\u003e Resting -\u003e Active ...\n/// Malicious agent: Unknown -\u003e Active -\u003e Fraudulent -\u003e Slashed\n/// Malicious agent: Unknown -\u003e Active -\u003e Unstaking -\u003e Fraudulent -\u003e Slashed\nenum AgentFlag {\n    Unknown,\n    Active,\n    Unstaking,\n    Resting,\n    Fraudulent,\n    Slashed\n}\n\n/// @notice Struct for storing an agent in the BondingManager contract.\nstruct AgentStatus {\n    AgentFlag flag;\n    uint32 domain;\n    uint32 index;\n}\n// 184 bits available for tight packing\n\nusing StructureUtils for AgentStatus global;\n\n/// @notice Potential statuses of an agent in terms of being in dispute\n/// - None: agent is not in dispute\n/// - Pending: agent is in unresolved dispute\n/// - Slashed: agent was in dispute that lead to agent being slashed\n/// Note: agent who won the dispute has their status reset to None\nenum DisputeFlag {\n    None,\n    Pending,\n    Slashed\n}\n\n/// @notice Struct for storing dispute status of an agent.\n/// @param flag         Dispute flag: None/Pending/Slashed.\n/// @param openedAt     Timestamp when the latest agent dispute was opened (zero if not opened).\n/// @param resolvedAt   Timestamp when the latest agent dispute was resolved (zero if not resolved).\nstruct DisputeStatus {\n    DisputeFlag flag;\n    uint40 openedAt;\n    uint40 resolvedAt;\n}\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\n/// @notice Struct representing the status of Destination contract.\n/// @param snapRootTime     Timestamp when latest snapshot root was accepted\n/// @param agentRootTime    Timestamp when latest agent root was accepted\n/// @param notaryIndex      Index of Notary who signed the latest agent root\nstruct DestinationStatus {\n    uint40 snapRootTime;\n    uint40 agentRootTime;\n    uint32 notaryIndex;\n}\n\n// ═══════════════════════════════ EXECUTION HUB ═══════════════════════════════\n\n/// @notice Potential statuses of the message in Execution Hub.\n/// - None: there hasn't been a valid attempt to execute the message yet\n/// - Failed: there was a valid attempt to execute the message, but recipient reverted\n/// - Success: there was a valid attempt to execute the message, and recipient did not revert\n/// Note: message can be executed until its status is Success\nenum MessageStatus {\n    None,\n    Failed,\n    Success\n}\n\nlibrary StructureUtils {\n    /// @notice Checks that Agent is Active\n    function verifyActive(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active) {\n            revert AgentNotActive();\n        }\n    }\n\n    /// @notice Checks that Agent is Unstaking\n    function verifyUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Unstaking) {\n            revert AgentNotUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Active or Unstaking\n    function verifyActiveUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active \u0026\u0026 status.flag != AgentFlag.Unstaking) {\n            revert AgentNotActiveNorUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Fraudulent\n    function verifyFraudulent(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Fraudulent) {\n            revert AgentNotFraudulent();\n        }\n    }\n\n    /// @notice Checks that Agent is not Unknown\n    function verifyKnown(AgentStatus memory status) internal pure {\n        if (status.flag == AgentFlag.Unknown) {\n            revert AgentUnknown();\n        }\n    }\n}\n\n// contracts/libs/memory/MemView.sol\n\n/// @dev MemView is an untyped view over a portion of memory to be used instead of `bytes memory`\ntype MemView is uint256;\n\n/// @dev Attach library functions to MemView\nusing MemViewLib for MemView global;\n\n/// @notice Library for operations with the memory views.\n/// Forked from https://github.com/summa-tx/memview-sol with several breaking changes:\n/// - The codebase is ported to Solidity 0.8\n/// - Custom errors are added\n/// - The runtime type checking is replaced with compile-time check provided by User-Defined Value Types\n///   https://docs.soliditylang.org/en/latest/types.html#user-defined-value-types\n/// - uint256 is used as the underlying type for the \"memory view\" instead of bytes29.\n///   It is wrapped into MemView custom type in order not to be confused with actual integers.\n/// - Therefore the \"type\" field is discarded, allowing to allocate 16 bytes for both view location and length\n/// - The documentation is expanded\n/// - Library functions unused by the rest of the codebase are removed\n//  - Very pretty code separators are added :)\nlibrary MemViewLib {\n    /// @notice Stack layout for uint256 (from highest bits to lowest)\n    /// (32 .. 16]      loc     16 bytes    Memory address of underlying bytes\n    /// (16 .. 00]      len     16 bytes    Length of underlying bytes\n\n    // ═══════════════════════════════════════════ BUILDING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Instantiate a new untyped memory view. This should generally not be called directly.\n     * Prefer `ref` wherever possible.\n     * @param loc_          The memory address\n     * @param len_          The length\n     * @return The new view with the specified location and length\n     */\n    function build(uint256 loc_, uint256 len_) internal pure returns (MemView) {\n        uint256 end_ = loc_ + len_;\n        // Make sure that a view is not constructed that points to unallocated memory\n        // as this could be indicative of a buffer overflow attack\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            if gt(end_, mload(0x40)) { end_ := 0 }\n        }\n        if (end_ == 0) {\n            revert UnallocatedMemory();\n        }\n        return _unsafeBuildUnchecked(loc_, len_);\n    }\n\n    /**\n     * @notice Instantiate a memory view from a byte array.\n     * @dev Note that due to Solidity memory representation, it is not possible to\n     * implement a deref, as the `bytes` type stores its len in memory.\n     * @param arr           The byte array\n     * @return The memory view over the provided byte array\n     */\n    function ref(bytes memory arr) internal pure returns (MemView) {\n        uint256 len_ = arr.length;\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 loc_;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // We add 0x20, so that the view starts exactly where the array data starts\n            loc_ := add(arr, 0x20)\n        }\n        return build(loc_, len_);\n    }\n\n    // ════════════════════════════════════════════ CLONING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to the new memory.\n     * @param memView       The memory view\n     * @return arr          The cloned byte array\n     */\n    function clone(MemView memView) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        unchecked {\n            _unsafeCopyTo(memView, ptr + 0x20);\n        }\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 len_ = memView.len();\n        uint256 footprint_ = memView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    /**\n     * @notice Copies all views, joins them into a new bytearray.\n     * @param memViews      The memory views\n     * @return arr          The new byte array with joined data behind the given views\n     */\n    function join(MemView[] memory memViews) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        MemView newView;\n        unchecked {\n            newView = _unsafeJoin(memViews, ptr + 0x20);\n        }\n        uint256 len_ = newView.len();\n        uint256 footprint_ = newView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    // ══════════════════════════════════════════ INSPECTING MEMORY VIEW ═══════════════════════════════════════════════\n\n    /**\n     * @notice Returns the memory address of the underlying bytes.\n     * @param memView       The memory view\n     * @return loc_         The memory address\n     */\n    function loc(MemView memView) internal pure returns (uint256 loc_) {\n        // loc is stored in the highest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u003e\u003e 128;\n    }\n\n    /**\n     * @notice Returns the number of bytes of the view.\n     * @param memView       The memory view\n     * @return len_         The length of the view\n     */\n    function len(MemView memView) internal pure returns (uint256 len_) {\n        // len is stored in the lowest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u0026 type(uint128).max;\n    }\n\n    /**\n     * @notice Returns the endpoint of `memView`.\n     * @param memView       The memory view\n     * @return end_         The endpoint of `memView`\n     */\n    function end(MemView memView) internal pure returns (uint256 end_) {\n        // The endpoint never overflows uint128, let alone uint256, so we could use unchecked math here\n        unchecked {\n            return memView.loc() + memView.len();\n        }\n    }\n\n    /**\n     * @notice Returns the number of memory words this memory view occupies, rounded up.\n     * @param memView       The memory view\n     * @return words_       The number of memory words\n     */\n    function words(MemView memView) internal pure returns (uint256 words_) {\n        // returning ceil(length / 32.0)\n        unchecked {\n            return (memView.len() + 31) \u003e\u003e 5;\n        }\n    }\n\n    /**\n     * @notice Returns the in-memory footprint of a fresh copy of the view.\n     * @param memView       The memory view\n     * @return footprint_   The in-memory footprint of a fresh copy of the view.\n     */\n    function footprint(MemView memView) internal pure returns (uint256 footprint_) {\n        // words() * 32\n        return memView.words() \u003c\u003c 5;\n    }\n\n    // ════════════════════════════════════════════ HASHING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the keccak256 hash of the underlying memory\n     * @param memView       The memory view\n     * @return digest       The keccak256 hash of the underlying memory\n     */\n    function keccak(MemView memView) internal pure returns (bytes32 digest) {\n        uint256 loc_ = memView.loc();\n        uint256 len_ = memView.len();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            digest := keccak256(loc_, len_)\n        }\n    }\n\n    /**\n     * @notice Adds a salt to the keccak256 hash of the underlying data and returns the keccak256 hash of the\n     * resulting data.\n     * @param memView       The memory view\n     * @return digestSalted keccak256(salt, keccak256(memView))\n     */\n    function keccakSalted(MemView memView, bytes32 salt) internal pure returns (bytes32 digestSalted) {\n        return keccak256(bytes.concat(salt, memView.keccak()));\n    }\n\n    // ════════════════════════════════════════════ SLICING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Safe slicing without memory modification.\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the given index\n     */\n    function slice(MemView memView, uint256 index_, uint256 len_) internal pure returns (MemView) {\n        uint256 loc_ = memView.loc();\n        // Ensure it doesn't overrun the view\n        if (loc_ + index_ + len_ \u003e memView.end()) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // loc_ + index_ \u003c= memView.end()\n            return build({loc_: loc_ + index_, len_: len_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing bytes from `index` to end(memView).\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @return The new view for the slice starting from the given index until the initial view endpoint\n     */\n    function sliceFrom(MemView memView, uint256 index_) internal pure returns (MemView) {\n        uint256 len_ = memView.len();\n        // Ensure it doesn't overrun the view\n        if (index_ \u003e len_) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // index_ \u003c= len_ =\u003e memView.loc() + index_ \u003c= memView.loc() + memView.len() == memView.end()\n            return build({loc_: memView.loc() + index_, len_: len_ - index_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the first `len` bytes.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the initial view beginning\n     */\n    function prefix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        return memView.slice({index_: 0, len_: len_});\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the last `len` byte.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length until the initial view endpoint\n     */\n    function postfix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        uint256 viewLen = memView.len();\n        // Ensure it doesn't overrun the view\n        if (len_ \u003e viewLen) {\n            revert ViewOverrun();\n        }\n        // Could do the unchecked math due to the check above\n        uint256 index_;\n        unchecked {\n            index_ = viewLen - len_;\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // len_ \u003c= memView.len() =\u003e memView.loc() \u003c= loc_ \u003c= memView.end()\n            return build({loc_: memView.loc() + viewLen - len_, len_: len_});\n        }\n    }\n\n    // ═══════════════════════════════════════════ INDEXING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Load up to 32 bytes from the view onto the stack.\n     * @dev Returns a bytes32 with only the `bytes_` HIGHEST bytes set.\n     * This can be immediately cast to a smaller fixed-length byte array.\n     * To automatically cast to an integer, use `indexUint`.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return result       The 32 byte result having only `bytes_` highest bytes set\n     */\n    function index(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (bytes32 result) {\n        if (bytes_ == 0) {\n            return bytes32(0);\n        }\n        // Can't load more than 32 bytes to the stack in one go\n        if (bytes_ \u003e 32) {\n            revert IndexedTooMuch();\n        }\n        // The last indexed byte should be within view boundaries\n        if (index_ + bytes_ \u003e memView.len()) {\n            revert ViewOverrun();\n        }\n        uint256 bitLength = bytes_ \u003c\u003c 3; // bytes_ * 8\n        uint256 loc_ = memView.loc();\n        // Get a mask with `bitLength` highest bits set\n        uint256 mask;\n        // 0x800...00 binary representation is 100...00\n        // sar stands for \"signed arithmetic shift\": https://en.wikipedia.org/wiki/Arithmetic_shift\n        // sar(N-1, 100...00) = 11...100..00, with exactly N highest bits set to 1\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            mask := sar(sub(bitLength, 1), 0x8000000000000000000000000000000000000000000000000000000000000000)\n        }\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load a full word using index offset, and apply mask to ignore non-relevant bytes\n            result := and(mload(add(loc_, index_)), mask)\n        }\n    }\n\n    /**\n     * @notice Parse an unsigned integer from the view at `index`.\n     * @dev Requires that the view have \u003e= `bytes_` bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return The unsigned integer\n     */\n    function indexUint(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (uint256) {\n        bytes32 indexedBytes = memView.index(index_, bytes_);\n        // `index()` returns left-aligned `bytes_`, while integers are right-aligned\n        // Shifting here to right-align with the full 32 bytes word: need to shift right `(32 - bytes_)` bytes\n        unchecked {\n            // memView.index() reverts when bytes_ \u003e 32, thus unchecked math\n            return uint256(indexedBytes) \u003e\u003e ((32 - bytes_) \u003c\u003c 3);\n        }\n    }\n\n    /**\n     * @notice Parse an address from the view at `index`.\n     * @dev Requires that the view have \u003e= 20 bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @return The address\n     */\n    function indexAddress(MemView memView, uint256 index_) internal pure returns (address) {\n        // index 20 bytes as `uint160`, and then cast to `address`\n        return address(uint160(memView.indexUint(index_, 20)));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns a memory view over the specified memory location\n    /// without checking if it points to unallocated memory.\n    function _unsafeBuildUnchecked(uint256 loc_, uint256 len_) private pure returns (MemView) {\n        // There is no scenario where loc or len would overflow uint128, so we omit this check.\n        // We use the highest 128 bits to encode the location and the lowest 128 bits to encode the length.\n        return MemView.wrap((loc_ \u003c\u003c 128) | len_);\n    }\n\n    /**\n     * @notice Copy the view to a location, return an unsafe memory reference\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memView       The memory view\n     * @param newLoc        The new location to copy the underlying view data\n     * @return The memory view over the unsafe memory with the copied underlying data\n     */\n    function _unsafeCopyTo(MemView memView, uint256 newLoc) private view returns (MemView) {\n        uint256 len_ = memView.len();\n        uint256 oldLoc = memView.loc();\n\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (newLoc \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        bool res;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // use the identity precompile (0x04) to copy\n            res := staticcall(gas(), 0x04, oldLoc, len_, newLoc, len_)\n        }\n        if (!res) revert PrecompileOutOfGas();\n        return _unsafeBuildUnchecked({loc_: newLoc, len_: len_});\n    }\n\n    /**\n     * @notice Join the views in memory, return an unsafe reference to the memory.\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memViews      The memory views\n     * @return The conjoined view pointing to the new memory\n     */\n    function _unsafeJoin(MemView[] memory memViews, uint256 location) private view returns (MemView) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (location \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        // Copy the views to the specified location one by one, by tracking the amount of copied bytes so far\n        uint256 offset = 0;\n        for (uint256 i = 0; i \u003c memViews.length;) {\n            MemView memView = memViews[i];\n            // We can use the unchecked math here as location + sum(view.length) will never overflow uint256\n            unchecked {\n                _unsafeCopyTo(memView, location + offset);\n                offset += memView.len();\n                ++i;\n            }\n        }\n        return _unsafeBuildUnchecked({loc_: location, len_: offset});\n    }\n}\n\n// contracts/libs/merkle/MerkleMath.sol\n\nlibrary MerkleMath {\n    // ═════════════════════════════════════════ BASIC MERKLE CALCULATIONS ═════════════════════════════════════════════\n\n    /**\n     * @notice Calculates the merkle root for the given leaf and merkle proof.\n     * @dev Will revert if proof length exceeds the tree height.\n     * @param index     Index of `leaf` in tree\n     * @param leaf      Leaf of the merkle tree\n     * @param proof     Proof of inclusion of `leaf` in the tree\n     * @param height    Height of the merkle tree\n     * @return root_    Calculated Merkle Root\n     */\n    function proofRoot(uint256 index, bytes32 leaf, bytes32[] memory proof, uint256 height)\n        internal\n        pure\n        returns (bytes32 root_)\n    {\n        // Proof length could not exceed the tree height\n        uint256 proofLen = proof.length;\n        if (proofLen \u003e height) revert TreeHeightTooLow();\n        root_ = leaf;\n        /// @dev Apply unchecked to all ++h operations\n        unchecked {\n            // Go up the tree levels from the leaf following the proof\n            for (uint256 h = 0; h \u003c proofLen; ++h) {\n                // Get a sibling node on current level: this is proof[h]\n                root_ = getParent(root_, proof[h], index, h);\n            }\n            // Go up to the root: the remaining siblings are EMPTY\n            for (uint256 h = proofLen; h \u003c height; ++h) {\n                root_ = getParent(root_, bytes32(0), index, h);\n            }\n        }\n    }\n\n    /**\n     * @notice Calculates the parent of a node on the path from one of the leafs to root.\n     * @param node          Node on a path from tree leaf to root\n     * @param sibling       Sibling for a given node\n     * @param leafIndex     Index of the tree leaf\n     * @param nodeHeight    \"Level height\" for `node` (ZERO for leafs, ORIGIN_TREE_HEIGHT for root)\n     */\n    function getParent(bytes32 node, bytes32 sibling, uint256 leafIndex, uint256 nodeHeight)\n        internal\n        pure\n        returns (bytes32 parent)\n    {\n        // Index for `node` on its \"tree level\" is (leafIndex / 2**height)\n        // \"Left child\" has even index, \"right child\" has odd index\n        if ((leafIndex \u003e\u003e nodeHeight) \u0026 1 == 0) {\n            // Left child\n            return getParent(node, sibling);\n        } else {\n            // Right child\n            return getParent(sibling, node);\n        }\n    }\n\n    /// @notice Calculates the parent of tow nodes in the merkle tree.\n    /// @dev We use implementation with H(0,0) = 0\n    /// This makes EVERY empty node in the tree equal to ZERO,\n    /// saving us from storing H(0,0), H(H(0,0), H(0, 0)), and so on\n    /// @param leftChild    Left child of the calculated node\n    /// @param rightChild   Right child of the calculated node\n    /// @return parent      Value for the node having above mentioned children\n    function getParent(bytes32 leftChild, bytes32 rightChild) internal pure returns (bytes32 parent) {\n        if (leftChild == bytes32(0) \u0026\u0026 rightChild == bytes32(0)) {\n            return 0;\n        } else {\n            return keccak256(bytes.concat(leftChild, rightChild));\n        }\n    }\n\n    // ════════════════════════════════ ROOT/PROOF CALCULATION FOR A LIST OF LEAFS ═════════════════════════════════════\n\n    /**\n     * @notice Calculates merkle root for a list of given leafs.\n     * Merkle Tree is constructed by padding the list with ZERO values for leafs until list length is `2**height`.\n     * Merkle Root is calculated for the constructed tree, and then saved in `leafs[0]`.\n     * \u003e Note:\n     * \u003e - `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * \u003e - Caller is expected not to reuse `hashes` list after the call, and only use `leafs[0]` value,\n     * which is guaranteed to contain the calculated merkle root.\n     * \u003e - root is calculated using the `H(0,0) = 0` Merkle Tree implementation. See MerkleTree.sol for details.\n     * @dev Amount of leaves should be at most `2**height`\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param height    Height of the Merkle Tree to construct\n     */\n    function calculateRoot(bytes32[] memory hashes, uint256 height) internal pure {\n        uint256 levelLength = hashes.length;\n        // Amount of hashes could not exceed amount of leafs in tree with the given height\n        if (levelLength \u003e (1 \u003c\u003c height)) revert TreeHeightTooLow();\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\": the amount of iterations for the for loop above.\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n            }\n        }\n    }\n\n    /**\n     * @notice Generates a proof of inclusion of a leaf in the list. If the requested index is outside\n     * of the list range, generates a proof of inclusion for an empty leaf (proof of non-inclusion).\n     * The Merkle Tree is constructed by padding the list with ZERO values until list length is a power of two\n     * __AND__ index is in the extended list range. For example:\n     *  - `hashes.length == 6` and `0 \u003c= index \u003c= 7` will \"extend\" the list to 8 entries.\n     *  - `hashes.length == 6` and `7 \u003c index \u003c= 15` will \"extend\" the list to 16 entries.\n     * \u003e Note: `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * Caller is expected not to reuse `hashes` list after the call.\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param index     Leaf index to generate the proof for\n     * @return proof    Generated merkle proof\n     */\n    function calculateProof(bytes32[] memory hashes, uint256 index) internal pure returns (bytes32[] memory proof) {\n        // Use only meaningful values for the shortened proof\n        // Check if index is within the list range (we want to generates proofs for outside leafs as well)\n        uint256 height = getHeight(index \u003c hashes.length ? hashes.length : (index + 1));\n        proof = new bytes32[](height);\n        uint256 levelLength = hashes.length;\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Use sibling for the merkle proof; `index^1` is index of our sibling\n                proof[h] = (index ^ 1 \u003c levelLength) ? hashes[index ^ 1] : bytes32(0);\n\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\"\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n                // Traverse to parent node\n                index \u003e\u003e= 1;\n            }\n        }\n    }\n\n    /// @notice Returns the height of the tree having a given amount of leafs.\n    function getHeight(uint256 leafs) internal pure returns (uint256 height) {\n        uint256 amount = 1;\n        while (amount \u003c leafs) {\n            unchecked {\n                ++height;\n            }\n            amount \u003c\u003c= 1;\n        }\n    }\n}\n\n// contracts/libs/stack/GasData.sol\n\n/// GasData in encoded data with \"basic information about gas prices\" for some chain.\ntype GasData is uint96;\n\nusing GasDataLib for GasData global;\n\n/// ChainGas is encoded data with given chain's \"basic information about gas prices\".\ntype ChainGas is uint128;\n\nusing GasDataLib for ChainGas global;\n\n/// Library for encoding and decoding GasData and ChainGas structs.\n/// # GasData\n/// `GasData` is a struct to store the \"basic information about gas prices\", that could\n/// be later used to approximate the cost of a message execution, and thus derive the\n/// minimal tip values for sending a message to the chain.\n/// \u003e - `GasData` is supposed to be cached by `GasOracle` contract, allowing to store the\n/// \u003e approximates instead of the exact values, and thus save on storage costs.\n/// \u003e - For instance, if `GasOracle` only updates the values on +- 10% change, having an\n/// \u003e 0.4% error on the approximates would be acceptable.\n/// `GasData` is supposed to be included in the Origin's state, which are synced across\n/// chains using Agent-signed snapshots and attestations.\n/// ## GasData stack layout (from highest bits to lowest)\n///\n/// | Position   | Field        | Type   | Bytes | Description                                         |\n/// | ---------- | ------------ | ------ | ----- | --------------------------------------------------- |\n/// | (012..010] | gasPrice     | uint16 | 2     | Gas price for the chain (in Wei per gas unit)       |\n/// | (010..008] | dataPrice    | uint16 | 2     | Calldata price (in Wei per byte of content)         |\n/// | (008..006] | execBuffer   | uint16 | 2     | Tx fee safety buffer for message execution (in Wei) |\n/// | (006..004] | amortAttCost | uint16 | 2     | Amortized cost for attestation submission (in Wei)  |\n/// | (004..002] | etherPrice   | uint16 | 2     | Chain's Ether Price / Mainnet Ether Price (in BWAD) |\n/// | (002..000] | markup       | uint16 | 2     | Markup for the message execution (in BWAD)          |\n/// \u003e See Number.sol for more details on `Number` type and BWAD (binary WAD) math.\n///\n/// ## ChainGas stack layout (from highest bits to lowest)\n///\n/// | Position   | Field   | Type   | Bytes | Description      |\n/// | ---------- | ------- | ------ | ----- | ---------------- |\n/// | (016..004] | gasData | uint96 | 12    | Chain's gas data |\n/// | (004..000] | domain  | uint32 | 4     | Chain's domain   |\nlibrary GasDataLib {\n    /// @dev Amount of bits to shift to gasPrice field\n    uint96 private constant SHIFT_GAS_PRICE = 10 * 8;\n    /// @dev Amount of bits to shift to dataPrice field\n    uint96 private constant SHIFT_DATA_PRICE = 8 * 8;\n    /// @dev Amount of bits to shift to execBuffer field\n    uint96 private constant SHIFT_EXEC_BUFFER = 6 * 8;\n    /// @dev Amount of bits to shift to amortAttCost field\n    uint96 private constant SHIFT_AMORT_ATT_COST = 4 * 8;\n    /// @dev Amount of bits to shift to etherPrice field\n    uint96 private constant SHIFT_ETHER_PRICE = 2 * 8;\n\n    /// @dev Amount of bits to shift to gasData field\n    uint128 private constant SHIFT_GAS_DATA = 4 * 8;\n\n    // ═════════════════════════════════════════════════ GAS DATA ══════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded GasData struct with the given fields.\n    /// @param gasPrice_        Gas price for the chain (in Wei per gas unit)\n    /// @param dataPrice_       Calldata price (in Wei per byte of content)\n    /// @param execBuffer_      Tx fee safety buffer for message execution (in Wei)\n    /// @param amortAttCost_    Amortized cost for attestation submission (in Wei)\n    /// @param etherPrice_      Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n    /// @param markup_          Markup for the message execution (in BWAD)\n    function encodeGasData(\n        Number gasPrice_,\n        Number dataPrice_,\n        Number execBuffer_,\n        Number amortAttCost_,\n        Number etherPrice_,\n        Number markup_\n    ) internal pure returns (GasData) {\n        // Number type wraps uint16, so could safely be casted to uint96\n        // forgefmt: disable-next-item\n        return GasData.wrap(\n            uint96(Number.unwrap(gasPrice_)) \u003c\u003c SHIFT_GAS_PRICE |\n            uint96(Number.unwrap(dataPrice_)) \u003c\u003c SHIFT_DATA_PRICE |\n            uint96(Number.unwrap(execBuffer_)) \u003c\u003c SHIFT_EXEC_BUFFER |\n            uint96(Number.unwrap(amortAttCost_)) \u003c\u003c SHIFT_AMORT_ATT_COST |\n            uint96(Number.unwrap(etherPrice_)) \u003c\u003c SHIFT_ETHER_PRICE |\n            uint96(Number.unwrap(markup_))\n        );\n    }\n\n    /// @notice Wraps padded uint256 value into GasData struct.\n    function wrapGasData(uint256 paddedGasData) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(paddedGasData));\n    }\n\n    /// @notice Returns the gas price, in Wei per gas unit.\n    function gasPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_GAS_PRICE));\n    }\n\n    /// @notice Returns the calldata price, in Wei per byte of content.\n    function dataPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_DATA_PRICE));\n    }\n\n    /// @notice Returns the tx fee safety buffer for message execution, in Wei.\n    function execBuffer(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_EXEC_BUFFER));\n    }\n\n    /// @notice Returns the amortized cost for attestation submission, in Wei.\n    function amortAttCost(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_AMORT_ATT_COST));\n    }\n\n    /// @notice Returns the ratio of Chain's Ether Price / Mainnet Ether Price, in BWAD math.\n    function etherPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_ETHER_PRICE));\n    }\n\n    /// @notice Returns the markup for the message execution, in BWAD math.\n    function markup(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data)));\n    }\n\n    // ════════════════════════════════════════════════ CHAIN DATA ═════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded ChainGas struct with the given fields.\n    /// @param gasData_ Chain's gas data\n    /// @param domain_  Chain's domain\n    function encodeChainGas(GasData gasData_, uint32 domain_) internal pure returns (ChainGas) {\n        // GasData type wraps uint96, so could safely be casted to uint128\n        return ChainGas.wrap(uint128(GasData.unwrap(gasData_)) \u003c\u003c SHIFT_GAS_DATA | uint128(domain_));\n    }\n\n    /// @notice Wraps padded uint256 value into ChainGas struct.\n    function wrapChainGas(uint256 paddedChainGas) internal pure returns (ChainGas) {\n        // Casting to uint128 will truncate the highest bits, which is the behavior we want\n        return ChainGas.wrap(uint128(paddedChainGas));\n    }\n\n    /// @notice Returns the chain's gas data.\n    function gasData(ChainGas data) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(ChainGas.unwrap(data) \u003e\u003e SHIFT_GAS_DATA));\n    }\n\n    /// @notice Returns the chain's domain.\n    function domain(ChainGas data) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(ChainGas.unwrap(data));\n    }\n\n    /// @notice Returns the hash for the list of ChainGas structs.\n    function snapGasHash(ChainGas[] memory snapGas) internal pure returns (bytes32 snapGasHash_) {\n        // Use assembly to calculate the hash of the array without copying it\n        // ChainGas takes a single word of storage, thus ChainGas[] is stored in the following way:\n        // 0x00: length of the array, in words\n        // 0x20: first ChainGas struct\n        // 0x40: second ChainGas struct\n        // And so on...\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Find the location where the array data starts, we add 0x20 to skip the length field\n            let loc := add(snapGas, 0x20)\n            // Load the length of the array (in words).\n            // Shifting left 5 bits is equivalent to multiplying by 32: this converts from words to bytes.\n            let len := shl(5, mload(snapGas))\n            // Calculate the hash of the array\n            snapGasHash_ := keccak256(loc, len)\n        }\n    }\n}\n\n// contracts/libs/stack/Header.sol\n\n/// Header is encoded data with \"general routing information\".\ntype Header is uint136;\n\nusing HeaderLib for Header global;\n\n/// Types of messages supported by Origin-Destination\n/// - Base: message sent by protocol user, contains tips\n/// - Manager: message sent between AgentManager contracts located on different chains, no tips\nenum MessageFlag {\n    Base,\n    Manager\n}\n\nusing HeaderLib for MessageFlag global;\n\n/// Library for formatting _the header part_ of _the messages used by Origin and Destination_.\n/// - Header represents general information for routing a Message for Origin and Destination.\n/// - Header occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n///\n/// # Header stack layout (from highest bits to lowest)\n///\n/// | Position   | Field            | Type   | Bytes | Description                             |\n/// | ---------- | ---------------- | ------ | ----- | --------------------------------------- |\n/// | (017..016] | flag             | uint8  | 1     | Flag specifying the type of message     |\n/// | (016..012] | origin           | uint32 | 4     | Domain where message originated         |\n/// | (012..008] | nonce            | uint32 | 4     | Message nonce on the origin domain      |\n/// | (008..004] | destination      | uint32 | 4     | Domain where message will be executed   |\n/// | (004..000] | optimisticPeriod | uint32 | 4     | Optimistic period that will be enforced |\nlibrary HeaderLib {\n    /// @dev Amount of bits to shift to flag field\n    uint136 private constant SHIFT_FLAG = 16 * 8;\n    /// @dev Amount of bits to shift to origin field\n    uint136 private constant SHIFT_ORIGIN = 12 * 8;\n    /// @dev Amount of bits to shift to nonce field\n    uint136 private constant SHIFT_NONCE = 8 * 8;\n    /// @dev Amount of bits to shift to destination field\n    uint136 private constant SHIFT_DESTINATION = 4 * 8;\n\n    /// @notice Returns an encoded header with provided fields\n    /// @param origin_              Domain of origin chain\n    /// @param nonce_               Message nonce on origin chain\n    /// @param destination_         Domain of destination chain\n    /// @param optimisticPeriod_    Optimistic period for message execution\n    function encodeHeader(\n        MessageFlag flag_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint32 destination_,\n        uint32 optimisticPeriod_\n    ) internal pure returns (Header) {\n        // All casts below are upcasts, so they are safe\n        // forgefmt: disable-next-item\n        return Header.wrap(\n            uint136(uint8(flag_)) \u003c\u003c SHIFT_FLAG |\n            uint136(origin_) \u003c\u003c SHIFT_ORIGIN |\n            uint136(nonce_) \u003c\u003c SHIFT_NONCE |\n            uint136(destination_) \u003c\u003c SHIFT_DESTINATION |\n            uint136(optimisticPeriod_)\n        );\n    }\n\n    /// @notice Checks that the header is a valid encoded header.\n    function isHeader(uint256 paddedHeader) internal pure returns (bool) {\n        // Check that flag is within range\n        return _flag(paddedHeader) \u003c= uint8(type(MessageFlag).max);\n    }\n\n    /// @notice Wraps the padded encoded request into a Header-typed value.\n    /// @dev The \"padded\" header is simply an encoded header casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded headers\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedHeader) internal pure returns (Header) {\n        // Check that flag is within range\n        if (!isHeader(paddedHeader)) revert FlagOutOfRange();\n        // Casting to uint136 will truncate the highest bits, which is the behavior we want\n        return Header.wrap(uint136(paddedHeader));\n    }\n\n    /// @notice Returns header's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Header header) internal pure returns (bytes32 hashedHeader) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store header in scratch space\n            mstore(0, header)\n            // Compute hash of header padded to 32 bytes\n            hashedHeader := keccak256(0, 32)\n        }\n    }\n\n    // ══════════════════════════════════════════════ HEADER SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns header's flag field\n    function flag(Header header) internal pure returns (MessageFlag) {\n        // We check that flag is within range when wrapping the header, so this cast is safe\n        return MessageFlag(_flag(Header.unwrap(header)));\n    }\n\n    /// @notice Returns header's origin field\n    function origin(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_ORIGIN);\n    }\n\n    /// @notice Returns header's nonce field\n    function nonce(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_NONCE);\n    }\n\n    /// @notice Returns header's destination field\n    function destination(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_DESTINATION);\n    }\n\n    /// @notice Returns header's optimistic seconds field\n    function optimisticPeriod(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns header's flag field without casting to MessageFlag\n    function _flag(uint256 paddedHeader) private pure returns (uint8) {\n        // Casting to uint8 will truncate the highest bits, which is the behavior we want\n        return uint8(paddedHeader \u003e\u003e SHIFT_FLAG);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n     * constructor.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall \u0026\u0026 _initialized \u003c 1) || (!AddressUpgradeable.isContract(address(this)) \u0026\u0026 _initialized == 1),\n            \"Initializable: contract is already initialized\"\n        );\n        _initialized = 1;\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: setting the version to 255 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing \u0026\u0026 _initialized \u003c version, \"Initializable: contract is already initialized\");\n        _initialized = version;\n        _initializing = true;\n        _;\n        _initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        require(_initializing, \"Initializable: contract is not initializing\");\n        _;\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized != type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint8) {\n        return _initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _initializing;\n    }\n}\n\n// contracts/interfaces/IAgentManager.sol\n\ninterface IAgentManager {\n    /**\n     * @notice Allows Inbox to open a Dispute between a Guard and a Notary, if they are both not in Dispute already.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Guard or Notary is already in Dispute.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Allows Inbox to slash an agent, if their fraud was proven.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Domain doesn't match the saved agent domain.\n     * @param domain    Domain where the Agent is active\n     * @param agent     Address of the Agent\n     * @param prover    Address that initially provided fraud proof\n     */\n    function slashAgent(uint32 domain, address agent, address prover) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest known root of the Agent Merkle Tree.\n     */\n    function agentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns the number of opened Disputes.\n     * @dev This includes the Disputes that have been resolved already.\n     */\n    function getDisputesAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns information about the dispute with the given index.\n     * @dev Will revert if dispute with given index hasn't been opened yet.\n     * @param index             Dispute index\n     * @return guard            Address of the Guard in the Dispute\n     * @return notary           Address of the Notary in the Dispute\n     * @return slashedAgent     Address of the Agent who was slashed when Dispute was resolved\n     * @return fraudProver      Address who provided fraud proof to resolve the Dispute\n     * @return reportPayload    Raw payload with report data that led to the Dispute\n     * @return reportSignature  Guard signature for the report payload\n     */\n    function getDispute(uint256 index)\n        external\n        view\n        returns (\n            address guard,\n            address notary,\n            address slashedAgent,\n            address fraudProver,\n            bytes memory reportPayload,\n            bytes memory reportSignature\n        );\n\n    /**\n     * @notice Returns the current Dispute status of a given agent. See Structures.sol for details.\n     * @dev Every returned value will be set to zero if agent was not slashed and is not in Dispute.\n     * `rival` and `disputePtr` will be set to zero if the agent was slashed without being in Dispute.\n     * @param agent         Agent address\n     * @return flag         Flag describing the current Dispute status for the agent: None/Pending/Slashed\n     * @return rival        Address of the rival agent in the Dispute\n     * @return fraudProver  Address who provided fraud proof to resolve the Dispute\n     * @return disputePtr   Index of the opened Dispute PLUS ONE. Zero if agent is not in Dispute.\n     */\n    function disputeStatus(address agent)\n        external\n        view\n        returns (DisputeFlag flag, address rival, address fraudProver, uint256 disputePtr);\n}\n\n// contracts/interfaces/IAgentSecured.sol\n\ninterface IAgentSecured {\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * between a Guard and a Notary has been opened.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * has been resolved due to one of the agents being slashed.\n     * \u003e `rivalIndex` will be ZERO, if the slashed agent was not in the Dispute.\n     * @param slashedIndex  Index of the slashed agent in the Agent Merkle Tree\n     * @param rivalIndex    Index of the their Dispute Rival in the Agent Merkle Tree\n     */\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the address of the local AgentManager contract, which is treated as\n     * the \"source of truth\" for agent statuses.\n     */\n    function agentManager() external view returns (address);\n\n    /**\n     * @notice Returns the address of the local Inbox contract, which is treated as\n     * the \"source of truth\" for agent-signed statements.\n     * @dev Inbox passes verified agent statements to `IAgentSecured` contract.\n     */\n    function inbox() external view returns (address);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns (flag, openedAt, resolvedAt) that describes the latest status of\n     * the latest dispute for an agent with a given index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param agentIndex    Agent index in the Agent Merkle Tree\n     * @return              Latest dispute status for the given agent: (flag, openedAt, resolvedAt)\n     */\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory);\n}\n\n// contracts/libs/memory/ByteString.sol\n\n/// @dev CallData is a memory view over the payload to be used for an external call, i.e.\n/// recipient.call(callData). Its length is always (4 + 32 * N) bytes:\n/// - First 4 bytes represent the function selector.\n/// - 32 * N bytes represent N words that function arguments occupy.\ntype CallData is uint256;\n\n/// @dev Attach library functions to CallData\nusing ByteString for CallData global;\n\n/// @dev Signature is a memory view over a \"65 bytes\" array representing a ECDSA signature.\ntype Signature is uint256;\n\n/// @dev Attach library functions to Signature\nusing ByteString for Signature global;\n\nlibrary ByteString {\n    using MemViewLib for bytes;\n\n    /**\n     * @dev non-compact ECDSA signatures are enforced as of OZ 4.7.3\n     *\n     *      Signature payload memory layout\n     * [000 .. 032) r   bytes32 32 bytes\n     * [032 .. 064) s   bytes32 32 bytes\n     * [064 .. 065) v   uint8    1 byte\n     */\n    uint256 internal constant SIGNATURE_LENGTH = 65;\n    uint256 private constant OFFSET_R = 0;\n    uint256 private constant OFFSET_S = 32;\n    uint256 private constant OFFSET_V = 64;\n\n    /**\n     * @dev Calldata memory layout\n     * [000 .. 004) selector    bytes4  4 bytes\n     *      Optional: N function arguments\n     * [004 .. 036) arg1        bytes32 32 bytes\n     *      ..\n     * [AAA .. END) argN        bytes32 32 bytes\n     */\n    uint256 internal constant SELECTOR_LENGTH = 4;\n    uint256 private constant OFFSET_SELECTOR = 0;\n    uint256 private constant OFFSET_ARGUMENTS = SELECTOR_LENGTH;\n\n    // ═════════════════════════════════════════════════ SIGNATURE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the signature payload from the given values.\n     * @dev Using ByteString.formatSignature({r: r, s: s, v: v}) will make sure\n     * that params are given in the right order.\n     */\n    function formatSignature(bytes32 r, bytes32 s, uint8 v) internal pure returns (bytes memory) {\n        return abi.encodePacked(r, s, v);\n    }\n\n    /**\n     * @notice Returns a Signature view over for the given payload.\n     * @dev Will revert if the payload is not a signature.\n     */\n    function castToSignature(bytes memory payload) internal pure returns (Signature) {\n        return castToSignature(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Signature view.\n     * @dev Will revert if the memory view is not over a signature.\n     */\n    function castToSignature(MemView memView) internal pure returns (Signature) {\n        if (!isSignature(memView)) revert UnformattedSignature();\n        return Signature.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a signature\n     */\n    function isSignature(MemView memView) internal pure returns (bool) {\n        return memView.len() == SIGNATURE_LENGTH;\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Signature signature) internal pure returns (MemView) {\n        return MemView.wrap(Signature.unwrap(signature));\n    }\n\n    // ═════════════════════════════════════════════ SIGNATURE SLICING ═════════════════════════════════════════════════\n\n    /// @notice Unpacks signature payload into (r, s, v) parameters.\n    /// @dev Make sure to verify signature length with isSignature() beforehand.\n    function toRSV(Signature signature) internal pure returns (bytes32 r, bytes32 s, uint8 v) {\n        // Get the underlying memory view\n        MemView memView = unwrap(signature);\n        r = memView.index({index_: OFFSET_R, bytes_: 32});\n        s = memView.index({index_: OFFSET_S, bytes_: 32});\n        // Can be safely casted to uint8, since we index a single byte\n        v = uint8(memView.indexUint({index_: OFFSET_V, bytes_: 1}));\n    }\n\n    // ═════════════════════════════════════════════════ CALLDATA ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the calldata with the modified arguments:\n     * the existing arguments are prepended with the arguments from the prefix.\n     * @dev Given:\n     *  - `calldata = abi.encodeWithSelector(foo.selector, d, e);`\n     *  - `prefix = abi.encode(a, b, c);`\n     *  - `a`, `b`, `c` are arguments of static type (i.e. not dynamically sized ones)\n     *      Then:\n     *  - Function will return abi.encodeWithSelector(foo.selector, a, c, c, d, e)\n     *  - Returned calldata will trigger `foo(a, b, c, d, e)` when used for a contract call.\n     * Note: for clarification as to what types are considered static, see\n     * https://docs.soliditylang.org/en/latest/abi-spec.html#formal-specification-of-the-encoding\n     * @param callData  Calldata that needs to be modified\n     * @param prefix    ABI-encoded arguments to use as the first arguments in the new calldata\n     * @return Modified calldata having prefix as the first arguments.\n     */\n    function addPrefix(CallData callData, bytes memory prefix) internal view returns (bytes memory) {\n        // Prefix should occupy a whole amount of words in memory\n        if (!_fullWords(prefix.length)) revert UnformattedCallDataPrefix();\n        MemView[] memory views = new MemView[](3);\n        // Use payload's function selector\n        views[0] = abi.encodePacked(callData.callSelector()).ref();\n        // Use prefix as the first arguments\n        views[1] = prefix.ref();\n        // Use payload's remaining arguments\n        views[2] = callData.arguments();\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a CallData view over for the given payload.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(bytes memory payload) internal pure returns (CallData) {\n        return castToCallData(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a CallData view.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(MemView memView) internal pure returns (CallData) {\n        if (!isCallData(memView)) revert UnformattedCallData();\n        return CallData.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a valid calldata, i.e.\n     * a function selector, followed by arbitrary amount of arguments.\n     */\n    function isCallData(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Calldata should at least have a function selector\n        if (length \u003c SELECTOR_LENGTH) return false;\n        // The remainder of the calldata should be exactly N memory words (N \u003e= 0)\n        return _fullWords(length - SELECTOR_LENGTH);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(CallData callData) internal pure returns (MemView) {\n        return MemView.wrap(CallData.unwrap(callData));\n    }\n\n    /// @notice Returns callData's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(CallData callData) internal pure returns (bytes32) {\n        return callData.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ CALLDATA SLICING ══════════════════════════════════════════════════\n\n    /**\n     * @notice Returns amount of memory words (32 byte chunks) the function arguments\n     * occupy in the calldata.\n     * @dev This might differ from amount of arguments supplied, if any of the arguments\n     * occupies more than one memory slot. It is true, however, that argument part of the payload\n     * occupies exactly N words, even for dynamic types like `bytes`\n     */\n    function argumentWords(CallData callData) internal pure returns (uint256) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        // Equivalent of (length - SELECTOR_LENGTH) / 32\n        return (memView.len() - SELECTOR_LENGTH) \u003e\u003e 5;\n    }\n\n    /// @notice Returns selector for the provided calldata.\n    function callSelector(CallData callData) internal pure returns (bytes4) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return bytes4(memView.index({index_: OFFSET_SELECTOR, bytes_: SELECTOR_LENGTH}));\n    }\n\n    /// @notice Returns abi encoded arguments for the provided calldata.\n    function arguments(CallData callData) internal pure returns (MemView) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return memView.sliceFrom({index_: OFFSET_ARGUMENTS});\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if length is full amount of memory words (32 bytes).\n    function _fullWords(uint256 length) internal pure returns (bool) {\n        // The equivalent of length % 32 == 0\n        return length \u0026 31 == 0;\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n    function __Context_init() internal onlyInitializing {\n    }\n\n    function __Context_init_unchained() internal onlyInitializing {\n    }\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[50] private __gap;\n}\n\n// contracts/libs/merkle/MerkleTree.sol\n\n/// `BaseTree` is a struct representing incremental merkle tree.\n/// - Contains only the current branch.\n/// - The number of inserted leaves is stored externally, and is later supplied for tree operations.\n/// - Has a fixed height of `ORIGIN_TREE_HEIGHT`.\n/// - Can store up to `2 ** ORIGIN_TREE_HEIGHT - 1` leaves.\n/// \u003e Note: the hash function for the tree `H(x, y)` is defined as:\n/// \u003e - `H(0,0) = 0`\n/// \u003e - `H(x,y) = keccak256(x, y), when (x != 0 || y != 0)`\n/// ## Invariant for leafs\n/// - The leftmost empty leaf has `index == count`, where `count` is the amount of the inserted leafs so far.\n/// - Value for any empty leaf or node is bytes32(0).\n/// ## Invariant for current branch\n/// `branch[i]` is always the value of a node on the i-th level.\n/// Levels are numbered from leafs to root: `0 .. ORIGIN_TREE_HEIGHT`.\n/// `branch[i]` stores the value for the node, such that:\n//  - The node is a \"left child\" (e.g. has an even index).\n/// - The node must have two non-empty children.\n/// - Out of all level's \"left child\" nodes with \"non-empty children\",\n/// the one with the biggest index (the rightmost one) is stored as `branch[i]`.\n/// \u003e __`branch` could be used to form a proof of inclusion for the first empty leaf (`index == count`).__\n/// _Here is how:_\n/// - Let's walk along the path from the \"first empty leaf\" to the root.\n/// - i-th bit of the \"first empty leaf\" index (which is equal to `count`) determines if the path's node\n/// for this i-th level is a \"left child\" or a \"right child\".\n/// - i-th bit in `count` is 0 → we are the left child on this level → sibling is the right child\n/// that does not exist yet → `proof[i] = bytes32(0)`.\n/// - i-th bit in `count` is 1 → we are the right child on this level → sibling is the left child\n/// sibling is the rightmost \"left child\" node on the level → `proof[i] = branch[i]`.\n/// \u003e Therefore `proof[i] = (count \u0026 (1 \u003c\u003c i)) == 0 ? bytes32(0) : branch[i])`\nstruct BaseTree {\n    bytes32[ORIGIN_TREE_HEIGHT] branch;\n}\n\nusing MerkleTree for BaseTree global;\n\n/// `HistoricalTree` is an incremental merkle tree keeping track of its historical merkle roots.\n/// \u003e - `roots[N]` is the root of the tree after `N` leafs were inserted\n/// \u003e - `roots[0] == bytes32(0)`\n/// @param tree     Incremental merkle tree\n/// @param roots    Historical merkle roots of the tree\nstruct HistoricalTree {\n    BaseTree tree;\n    bytes32[] roots;\n}\n\nusing MerkleTree for HistoricalTree global;\n\n/// `DynamicTree` is a struct representing a Merkle Tree with `2**AGENT_TREE_HEIGHT` leaves.\n/// - A single operation is available: update value for leaf with an arbitrary index (which might be a non-empty leaf).\n/// - This is done by requesting the proof of inclusion for the old value, which is used to both\n/// verify the old value, and calculate the new root.\n/// \u003e Based on Original idea from [ER forum post](https://ethresear.ch/t/efficient-on-chain-dynamic-merkle-tree/11054).\nstruct DynamicTree {\n    bytes32 root;\n}\n\nusing MerkleTree for DynamicTree global;\n\n/// MerkleTree is work based on Nomad's Merkle.sol, which is used under MIT OR Apache-2.0\n/// [link](https://github.com/nomad-xyz/monorepo/blob/main/packages/contracts-core/contracts/libs/Merkle.sol).\n/// With the following changes:\n/// - Adapted for Solidity 0.8.x.\n/// - Amount of tree leaves stored externally.\n/// - Added thorough documentation.\n/// - `H(0,0) = 0` optimization from [ER forum post](https://ethresear.ch/t/optimizing-sparse-merkle-trees/3751/6).\n/// \u003e Nomad's Merkle.sol is work based on eth2 deposit contract, which is used under CC0-1.0\n///[link](https://github.com/ethereum/deposit_contract/blob/dev/deposit_contract/contracts/validator_registration.v.py).\n/// With the following changes:\n/// \u003e - Implemented in Solidity 0.7.6 (eth2 deposit contract implemented in Vyper).\n/// \u003e - `H() = keccak256()` is used as the hashing function instead of `sha256()`.\nlibrary MerkleTree {\n    /// @dev For root calculation we need at least one empty leaf, thus the minus one in the formula.\n    uint256 internal constant MAX_LEAVES = 2 ** ORIGIN_TREE_HEIGHT - 1;\n\n    // ═════════════════════════════════════════════════ BASE TREE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Inserts `node` into merkle tree\n     * @dev Reverts if tree is full\n     * @param newCount  Amount of inserted leaves in the tree after the insertion (i.e. current + 1)\n     * @param node      Element to insert into tree\n     */\n    function insertBase(BaseTree storage tree, uint256 newCount, bytes32 node) internal {\n        if (newCount \u003e MAX_LEAVES) revert MerkleTreeFull();\n        // We go up the tree following the branch from the empty leaf AFTER the just inserted one.\n        // We stop when we find the first \"right child\" node.\n        // Its sibling is now the rightmost \"left child\" node that has two non-empty children.\n        // Therefore we need to update `tree.branch` value on this level.\n        // One could see that `tree.branch` value on lower and higher levels remain unchanged.\n\n        // Loop invariant: `node` is the current level's value for the branch from JUST INSERTED leaf\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            if ((newCount \u0026 1) == 1) {\n                // Found the first \"right child\" node on the branch from EMPTY leaf\n                // `node` is the value for node on branch from JUST INSERTED leaf\n                // Which in this case is the \"left child\".\n                // We update tree.branch and exit\n                tree.branch[i] = node;\n                return;\n            }\n            // On the branch from EMPTY leaf this is still a \"left child\".\n            // Meaning on branch from JUST INSERTED leaf, `node` is a right child.\n            // We compute value for `node` parent using `tree.branch` invariant:\n            // This is the rightmost \"left child\" node, which would be sibling of `node`.\n            node = MerkleMath.getParent(tree.branch[i], node);\n            // Get the parent index, and go to the next tree level\n            newCount \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n        // As the loop should always end prematurely with the `return` statement,\n        // this code should be unreachable. We assert `false` just to be safe.\n        assert(false);\n    }\n\n    /**\n     * @notice Calculates and returns current root of the merkle tree.\n     * @param count     Current amount of inserted leaves in the tree\n     * @return current  Calculated root of `tree`\n     */\n    function rootBase(BaseTree storage tree, uint256 count) internal view returns (bytes32 current) {\n        // To calculate the root we follow the branch of first EMPTY leaf (index == count)\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            // Check if we are the left or the right child on the current level\n            if ((count \u0026 1) == 1) {\n                // We are the right child. Our sibling is the \"rightmost\" \"left-child\" node\n                // that has two non-empty children → sibling is `tree.branch[i]`\n                current = MerkleMath.getParent(tree.branch[i], current);\n            } else {\n                // We are the left child. Our sibling does not exist yet → sibling is EMPTY\n                current = MerkleMath.getParent(current, bytes32(0));\n            }\n            // Get the parent index, and go to the next tree level\n            count \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    // ══════════════════════════════════════════════ HISTORICAL TREE ══════════════════════════════════════════════════\n\n    /// @notice Initializes the historical roots for the tree by inserting an empty root.\n    // solhint-disable-next-line ordering\n    function initializeRoots(HistoricalTree storage tree) internal returns (bytes32 savedRoot) {\n        // This should only be called once, when the contract is initialized\n        assert(tree.roots.length == 0);\n        // Save root for empty merkle tree: bytes32(0)\n        tree.roots.push(savedRoot);\n    }\n\n    /// @notice Inserts a new leaf into the merkle tree.\n    /// @dev Reverts if tree is full.\n    /// @param node         Element to insert into tree\n    /// @return newRoot     Merkle root after the leaf was inserted\n    function insert(HistoricalTree storage tree, bytes32 node) internal returns (bytes32 newRoot) {\n        // Tree count after the new leaf will be inserted (we store roots[0] as root of empty tree)\n        uint256 newCount = tree.roots.length;\n        tree.tree.insertBase(newCount, node);\n        // Save the new root\n        newRoot = tree.tree.rootBase(newCount);\n        tree.roots.push(newRoot);\n    }\n\n    /// @notice Returns the historical root of the merkle tree.\n    /// @dev Reverts if not enough leafs have been inserted.\n    /// @param count            Amount of leafs in the tree at some point of time\n    /// @return historicalRoot  Merkle root after `count` leafs were inserted\n    function root(HistoricalTree storage tree, uint256 count) internal view returns (bytes32 historicalRoot) {\n        if (count \u003e= tree.roots.length) revert NotEnoughLeafs();\n        return tree.roots[count];\n    }\n\n    // ═══════════════════════════════════════════════ DYNAMIC TREE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Updates the value for the leaf with the given index in the Dynamic Merkle Tree.\n     * @dev Will revert if incorrect proof of inclusion for old value is supplied.\n     * @param tree          Dynamic merkle tree\n     * @param index         Index of the leaf to update\n     * @param oldValue      Previous value of the leaf\n     * @param branch        Proof of inclusion of previous value into the tree\n     * @param newValue      New leaf value to assign\n     * @return newRoot      New value for the Merkle Root after the leaf is updated\n     */\n    function update(\n        DynamicTree storage tree,\n        uint256 index,\n        bytes32 oldValue,\n        bytes32[] memory branch,\n        bytes32 newValue\n    ) internal returns (bytes32 newRoot) {\n        // Check that the old value + proof result in a correct root\n        if (MerkleMath.proofRoot(index, oldValue, branch, AGENT_TREE_HEIGHT) != tree.root) {\n            revert LeafNotProven();\n        }\n        // New root is new value + the same proof (values for sibling nodes are not updated)\n        newRoot = MerkleMath.proofRoot(index, newValue, branch, AGENT_TREE_HEIGHT);\n        // Write the new root\n        tree.root = newRoot;\n    }\n}\n\n// contracts/libs/stack/Tips.sol\n\n/// Tips is encoded data with \"tips paid for sending a base message\".\n/// Note: even though uint256 is also an underlying type for MemView, Tips is stored ON STACK.\ntype Tips is uint256;\n\nusing TipsLib for Tips global;\n\n/// # Tips\n/// Library for formatting _the tips part_ of _the base messages_.\n///\n/// ## How the tips are awarded\n/// Tips are paid for sending a base message, and are split across all the agents that\n/// made the message execution on destination chain possible.\n/// ### Summit tips\n/// Split between:\n///     - Guard posting a snapshot with state ST_G for the origin chain.\n///     - Notary posting a snapshot SN_N using ST_G. This creates attestation A.\n///     - Notary posting a message receipt after it is executed on destination chain.\n/// ### Attestation tips\n/// Paid to:\n///     - Notary posting attestation A to destination chain.\n/// ### Execution tips\n/// Paid to:\n///     - First executor performing a valid execution attempt (correct proofs, optimistic period over),\n///      using attestation A to prove message inclusion on origin chain, whether the recipient reverted or not.\n/// ### Delivery tips.\n/// Paid to:\n///     - Executor who successfully executed the message on destination chain.\n///\n/// ## Tips encoding\n/// - Tips occupy a single storage word, and thus are stored on stack instead of being stored in memory.\n/// - The actual tip values should be determined by multiplying stored values by divided by TIPS_MULTIPLIER=2**32.\n/// - Tips are packed into a single word of storage, while allowing real values up to ~8*10**28 for every tip category.\n/// \u003e The only downside is that the \"real tip values\" are now multiplies of ~4*10**9, which should be fine even for\n/// the chains with the most expensive gas currency.\n/// # Tips stack layout (from highest bits to lowest)\n///\n/// | Position   | Field          | Type   | Bytes | Description                                                |\n/// | ---------- | -------------- | ------ | ----- | ---------------------------------------------------------- |\n/// | (032..024] | summitTip      | uint64 | 8     | Tip for agents interacting with Summit contract            |\n/// | (024..016] | attestationTip | uint64 | 8     | Tip for Notary posting attestation to Destination contract |\n/// | (016..008] | executionTip   | uint64 | 8     | Tip for valid execution attempt on destination chain       |\n/// | (008..000] | deliveryTip    | uint64 | 8     | Tip for successful message delivery on destination chain   |\n\nlibrary TipsLib {\n    using SafeCast for uint256;\n\n    /// @dev Amount of bits to shift to summitTip field\n    uint256 private constant SHIFT_SUMMIT_TIP = 24 * 8;\n    /// @dev Amount of bits to shift to attestationTip field\n    uint256 private constant SHIFT_ATTESTATION_TIP = 16 * 8;\n    /// @dev Amount of bits to shift to executionTip field\n    uint256 private constant SHIFT_EXECUTION_TIP = 8 * 8;\n\n    // ═══════════════════════════════════════════════════ TIPS ════════════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips with the given fields\n    /// @param summitTip_        Tip for agents interacting with Summit contract, divided by TIPS_MULTIPLIER\n    /// @param attestationTip_   Tip for Notary posting attestation to Destination contract, divided by TIPS_MULTIPLIER\n    /// @param executionTip_     Tip for valid execution attempt on destination chain, divided by TIPS_MULTIPLIER\n    /// @param deliveryTip_      Tip for successful message delivery on destination chain, divided by TIPS_MULTIPLIER\n    function encodeTips(uint64 summitTip_, uint64 attestationTip_, uint64 executionTip_, uint64 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // forgefmt: disable-next-item\n        return Tips.wrap(\n            uint256(summitTip_) \u003c\u003c SHIFT_SUMMIT_TIP |\n            uint256(attestationTip_) \u003c\u003c SHIFT_ATTESTATION_TIP |\n            uint256(executionTip_) \u003c\u003c SHIFT_EXECUTION_TIP |\n            uint256(deliveryTip_)\n        );\n    }\n\n    /// @notice Convenience function to encode tips with uint256 values.\n    function encodeTips256(uint256 summitTip_, uint256 attestationTip_, uint256 executionTip_, uint256 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // In practice, the tips amounts are not supposed to be higher than 2**96, and with 32 bits of granularity\n        // using uint64 is enough to store the values. However, we still check for overflow just in case.\n        // TODO: consider using Number type to store the tips values.\n        return encodeTips({\n            summitTip_: (summitTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            attestationTip_: (attestationTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            executionTip_: (executionTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            deliveryTip_: (deliveryTip_ \u003e\u003e TIPS_GRANULARITY).toUint64()\n        });\n    }\n\n    /// @notice Wraps the padded encoded tips into a Tips-typed value.\n    /// @dev There is no actual padding here, as the underlying type is already uint256,\n    /// but we include this function for consistency and to be future-proof, if tips will eventually use anything\n    /// smaller than uint256.\n    function wrapPadded(uint256 paddedTips) internal pure returns (Tips) {\n        return Tips.wrap(paddedTips);\n    }\n\n    /**\n     * @notice Returns a formatted Tips payload specifying empty tips.\n     * @return Formatted tips\n     */\n    function emptyTips() internal pure returns (Tips) {\n        return Tips.wrap(0);\n    }\n\n    /// @notice Returns tips's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Tips tips) internal pure returns (bytes32 hashedTips) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store tips in scratch space\n            mstore(0, tips)\n            // Compute hash of tips padded to 32 bytes\n            hashedTips := keccak256(0, 32)\n        }\n    }\n\n    // ═══════════════════════════════════════════════ TIPS SLICING ════════════════════════════════════════════════════\n\n    /// @notice Returns summitTip field\n    function summitTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_SUMMIT_TIP);\n    }\n\n    /// @notice Returns attestationTip field\n    function attestationTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_ATTESTATION_TIP);\n    }\n\n    /// @notice Returns executionTip field\n    function executionTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_EXECUTION_TIP);\n    }\n\n    /// @notice Returns deliveryTip field\n    function deliveryTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips));\n    }\n\n    // ════════════════════════════════════════════════ TIPS VALUE ═════════════════════════════════════════════════════\n\n    /// @notice Returns total value of the tips payload.\n    /// This is the sum of the encoded values, scaled up by TIPS_MULTIPLIER\n    function value(Tips tips) internal pure returns (uint256 value_) {\n        value_ = uint256(tips.summitTip()) + tips.attestationTip() + tips.executionTip() + tips.deliveryTip();\n        value_ \u003c\u003c= TIPS_GRANULARITY;\n    }\n\n    /// @notice Increases the delivery tip to match the new value.\n    function matchValue(Tips tips, uint256 newValue) internal pure returns (Tips newTips) {\n        uint256 oldValue = tips.value();\n        if (newValue \u003c oldValue) revert TipsValueTooLow();\n        // We want to increase the delivery tip, while keeping the other tips the same\n        unchecked {\n            uint256 delta = (newValue - oldValue) \u003e\u003e TIPS_GRANULARITY;\n            // `delta` fits into uint224, as TIPS_GRANULARITY is 32, so this never overflows uint256.\n            // In practice, this will never overflow uint64 as well, but we still check it just in case.\n            if (delta + tips.deliveryTip() \u003e type(uint64).max) revert TipsOverflow();\n            // Delivery tips occupy lowest 8 bytes, so we can just add delta to the tips value\n            // to effectively increase the delivery tip (knowing that delta fits into uint64).\n            newTips = Tips.wrap(Tips.unwrap(tips) + delta);\n        }\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    function __Ownable_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable_init_unchained() internal onlyInitializing {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n    function __Ownable2Step_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable2Step_init_unchained() internal onlyInitializing {\n    }\n    address private _pendingOwner;\n\n    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Returns the address of the pending owner.\n     */\n    function pendingOwner() public view virtual returns (address) {\n        return _pendingOwner;\n    }\n\n    /**\n     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual override onlyOwner {\n        _pendingOwner = newOwner;\n        emit OwnershipTransferStarted(owner(), newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual override {\n        delete _pendingOwner;\n        super._transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev The new owner accepts the ownership transfer.\n     */\n    function acceptOwnership() public virtual {\n        address sender = _msgSender();\n        require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n        _transferOwnership(sender);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// contracts/libs/memory/State.sol\n\n/// State is a memory view over a formatted state payload.\ntype State is uint256;\n\nusing StateLib for State global;\n\n/// # State\n/// State structure represents the state of Origin contract at some point of time.\n/// - State is structured in a way to track the updates of the Origin Merkle Tree.\n/// - State includes root of the Origin Merkle Tree, origin domain and some additional metadata.\n/// ## Origin Merkle Tree\n/// Hash of every sent message is inserted in the Origin Merkle Tree, which changes\n/// the value of Origin Merkle Root (which is the root for the mentioned tree).\n/// - Origin has a single Merkle Tree for all messages, regardless of their destination domain.\n/// - This leads to Origin state being updated if and only if a message was sent in a block.\n/// - Origin contract is a \"source of truth\" for states: a state is considered \"valid\" in its Origin,\n/// if it matches the state of the Origin contract after the N-th (nonce) message was sent.\n///\n/// # Memory layout of State fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                    |\n/// | ---------- | ----------- | ------- | ----- | ------------------------------ |\n/// | [000..032) | root        | bytes32 | 32    | Root of the Origin Merkle Tree |\n/// | [032..036) | origin      | uint32  | 4     | Domain where Origin is located |\n/// | [036..040) | nonce       | uint32  | 4     | Amount of sent messages        |\n/// | [040..045) | blockNumber | uint40  | 5     | Block of last sent message     |\n/// | [045..050) | timestamp   | uint40  | 5     | Time of last sent message      |\n/// | [050..062) | gasData     | uint96  | 12    | Gas data for the chain         |\n///\n/// @dev State could be used to form a Snapshot to be signed by a Guard or a Notary.\nlibrary StateLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_ROOT = 0;\n    uint256 private constant OFFSET_ORIGIN = 32;\n    uint256 private constant OFFSET_NONCE = 36;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 40;\n    uint256 private constant OFFSET_TIMESTAMP = 45;\n    uint256 private constant OFFSET_GAS_DATA = 50;\n\n    // ═══════════════════════════════════════════════════ STATE ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted State payload with provided fields\n     * @param root_         New merkle root\n     * @param origin_       Domain of Origin's chain\n     * @param nonce_        Nonce of the merkle root\n     * @param blockNumber_  Block number when root was saved in Origin\n     * @param timestamp_    Block timestamp when root was saved in Origin\n     * @param gasData_      Gas data for the chain\n     * @return Formatted state\n     */\n    function formatState(\n        bytes32 root_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_,\n        GasData gasData_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(root_, origin_, nonce_, blockNumber_, timestamp_, gasData_);\n    }\n\n    /**\n     * @notice Returns a State view over the given payload.\n     * @dev Will revert if the payload is not a state.\n     */\n    function castToState(bytes memory payload) internal pure returns (State) {\n        return castToState(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a State view.\n     * @dev Will revert if the memory view is not over a state.\n     */\n    function castToState(MemView memView) internal pure returns (State) {\n        if (!isState(memView)) revert UnformattedState();\n        return State.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted State.\n    function isState(MemView memView) internal pure returns (bool) {\n        return memView.len() == STATE_LENGTH;\n    }\n\n    /// @notice Returns the hash of a State, that could be later signed by a Guard to signal\n    /// that the state is invalid.\n    function hashInvalid(State state) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(stateInvalidSalt, keccak(state))\n        return state.unwrap().keccakSalted(STATE_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(State state) internal pure returns (MemView) {\n        return MemView.wrap(State.unwrap(state));\n    }\n\n    /// @notice Compares two State structures.\n    function equals(State a, State b) internal pure returns (bool) {\n        // Length of a State payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═══════════════════════════════════════════════ STATE HASHING ═══════════════════════════════════════════════════\n\n    /// @notice Returns the hash of the State.\n    /// @dev We are using the Merkle Root of a tree with two leafs (see below) as state hash.\n    function leaf(State state) internal pure returns (bytes32) {\n        (bytes32 leftLeaf_, bytes32 rightLeaf_) = state.subLeafs();\n        // Final hash is the parent of these leafs\n        return keccak256(bytes.concat(leftLeaf_, rightLeaf_));\n    }\n\n    /// @notice Returns \"sub-leafs\" of the State. Hash of these \"sub leafs\" is going to be used\n    /// as a \"state leaf\" in the \"Snapshot Merkle Tree\".\n    /// This enables proving that leftLeaf = (root, origin) was a part of the \"Snapshot Merkle Tree\",\n    /// by combining `rightLeaf` with the remainder of the \"Snapshot Merkle Proof\".\n    function subLeafs(State state) internal pure returns (bytes32 leftLeaf_, bytes32 rightLeaf_) {\n        MemView memView = state.unwrap();\n        // Left leaf is (root, origin)\n        leftLeaf_ = memView.prefix({len_: OFFSET_NONCE}).keccak();\n        // Right leaf is (metadata), or (nonce, blockNumber, timestamp)\n        rightLeaf_ = memView.sliceFrom({index_: OFFSET_NONCE}).keccak();\n    }\n\n    /// @notice Returns the left \"sub-leaf\" of the State.\n    function leftLeaf(bytes32 root_, uint32 origin_) internal pure returns (bytes32) {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(root_, origin_));\n    }\n\n    /// @notice Returns the right \"sub-leaf\" of the State.\n    function rightLeaf(uint32 nonce_, uint40 blockNumber_, uint40 timestamp_, GasData gasData_)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(nonce_, blockNumber_, timestamp_, gasData_));\n    }\n\n    // ═══════════════════════════════════════════════ STATE SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns a historical Merkle root from the Origin contract.\n    function root(State state) internal pure returns (bytes32) {\n        return state.unwrap().index({index_: OFFSET_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns domain of chain where the Origin contract is deployed.\n    function origin(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns nonce of Origin contract at the time, when `root` was the Merkle root.\n    function nonce(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when `root` was saved in Origin.\n    function blockNumber(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when `root` was saved in Origin.\n    /// @dev This is the timestamp according to the origin chain.\n    function timestamp(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n\n    /// @notice Returns gas data for the chain.\n    function gasData(State state) internal pure returns (GasData) {\n        return GasDataLib.wrapGasData(state.unwrap().indexUint({index_: OFFSET_GAS_DATA, bytes_: GAS_DATA_LENGTH}));\n    }\n}\n\n// contracts/libs/memory/BaseMessage.sol\n\n/// BaseMessage is a memory view over the base message supported by Origin-Destination\ntype BaseMessage is uint256;\n\nusing BaseMessageLib for BaseMessage global;\n\n/// BaseMessage structure represents a base message sent via the Origin-Destination contracts.\n/// - It only contains data relevant to the base message, the rest of data is encoded in the message header.\n/// - `sender` and `recipient` for EVM chains are EVM addresses casted to bytes32, while preserving left-alignment.\n/// - `tips` and `request` parameters are specified by a message sender\n/// \u003e Origin will calculate minimum tips for given request and content length, and will reject messages with tips\n/// lower than that.\n///\n/// # Memory layout of BaseMessage fields\n///\n/// | Position   | Field     | Type    | Bytes | Description                            |\n/// | ---------- | --------- | ------- | ----- | -------------------------------------- |\n/// | [000..032) | tips      | uint256 | 32    | Encoded tips paid on origin chain      |\n/// | [032..064) | sender    | bytes32 | 32    | Sender address on origin chain         |\n/// | [064..096) | recipient | bytes32 | 32    | Recipient address on destination chain |\n/// | [096..116) | request   | uint160 | 20    | Encoded request for message execution  |\n/// | [104..AAA) | content   | bytes   | ??    | Content to be passed to recipient      |\nlibrary BaseMessageLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_TIPS = 0;\n    uint256 private constant OFFSET_SENDER = 32;\n    uint256 private constant OFFSET_RECIPIENT = 64;\n    uint256 private constant OFFSET_REQUEST = OFFSET_RECIPIENT + TIPS_LENGTH;\n    uint256 private constant OFFSET_CONTENT = OFFSET_REQUEST + REQUEST_LENGTH;\n\n    // ═══════════════════════════════════════════════ BASE MESSAGE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted BaseMessage payload with provided fields.\n     * @param tips_         Encoded tips information\n     * @param sender_       Sender address on origin chain\n     * @param recipient_    Recipient address on destination chain\n     * @param request_      Encoded request for message execution\n     * @param content_      Raw content to be passed to recipient on destination chain\n     * @return Formatted base message\n     */\n    function formatBaseMessage(Tips tips_, bytes32 sender_, bytes32 recipient_, Request request_, bytes memory content_)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return abi.encodePacked(tips_, sender_, recipient_, request_, content_);\n    }\n\n    /**\n     * @notice Returns a BaseMessage view over the given payload.\n     * @dev Will revert if the payload is not a base message.\n     */\n    function castToBaseMessage(bytes memory payload) internal pure returns (BaseMessage) {\n        return castToBaseMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a BaseMessage view.\n     * @dev Will revert if the memory view is not over a base message payload.\n     */\n    function castToBaseMessage(MemView memView) internal pure returns (BaseMessage) {\n        if (!isBaseMessage(memView)) revert UnformattedBaseMessage();\n        return BaseMessage.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted BaseMessage.\n    function isBaseMessage(MemView memView) internal pure returns (bool) {\n        // Check if sender, recipient, tips fields exist\n        return (memView.len() \u003e= OFFSET_CONTENT);\n        // Content could be empty, so we don't check that\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(BaseMessage baseMessage) internal pure returns (MemView) {\n        return MemView.wrap(BaseMessage.unwrap(baseMessage));\n    }\n\n    /// @notice Returns baseMessage's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        // We hash \"tips\" and \"everything but tips\" to make tips proofs easier to verify\n        return MerkleMath.getParent(baseMessage.tips().leaf(), baseMessage.bodyLeaf());\n    }\n\n    /// @notice Returns hash for the \"everything but tips\" part of the base message.\n    function bodyLeaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_SENDER}).keccak();\n    }\n\n    // ═══════════════════════════════════════════ BASE MESSAGE SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips paid on origin chain.\n    function tips(BaseMessage baseMessage) internal pure returns (Tips) {\n        return TipsLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_TIPS, bytes_: TIPS_LENGTH})));\n    }\n\n    /// @notice Returns sender address on origin chain.\n    function sender(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_SENDER, bytes_: 32});\n    }\n\n    /// @notice Returns recipient address on destination chain.\n    function recipient(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_RECIPIENT, bytes_: 32});\n    }\n\n    /// @notice Returns an encoded request for message execution on destination chain.\n    function request(BaseMessage baseMessage) internal pure returns (Request) {\n        return RequestLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_REQUEST, bytes_: REQUEST_LENGTH})));\n    }\n\n    /// @notice Returns an untyped memory view over the content to be passed to recipient.\n    function content(BaseMessage baseMessage) internal pure returns (MemView) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_CONTENT});\n    }\n}\n\n// contracts/base/MessagingBase.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for all messaging contracts.\n * - Provides context on the local chain's domain.\n * - Provides ownership functionality.\n * - Will be providing pausing functionality when it is implemented.\n */\nabstract contract MessagingBase is MultiCallable, Versioned, Ownable2StepUpgradeable {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @notice Domain of the local chain, set once upon contract creation\n    uint32 public immutable localDomain;\n    // @notice Domain of the Synapse chain, set once upon contract creation\n    uint32 public immutable synapseDomain;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev gap for upgrade safety\n    uint256[50] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    constructor(string memory version_, uint32 synapseDomain_) Versioned(version_) {\n        localDomain = ChainContext.chainId();\n        synapseDomain = synapseDomain_;\n    }\n\n    // TODO: Implement pausing\n\n    /**\n     * @dev Should be impossible to renounce ownership;\n     * we override OpenZeppelin OwnableUpgradeable's\n     * implementation of renounceOwnership to make it a no-op\n     */\n    function renounceOwnership() public override onlyOwner {} //solhint-disable-line no-empty-blocks\n}\n\n// contracts/libs/memory/Message.sol\n\n/// Message is a memory over over a formatted message payload.\ntype Message is uint256;\n\nusing MessageLib for Message global;\n\n/// Library for formatting the various messages supported by Origin and Destination.\n///\n/// # Message memory layout\n///\n/// | Position   | Field  | Type    | Bytes | Description                                             |\n/// | ---------- | ------ | ------- | ----- | ------------------------------------------------------- |\n/// | [000..017) | header | uint136 | 17    | Encoded general routing information for the message     |\n/// | [017..AAA) | body   | bytes   | ??    | Formatted payload (according to flag) with message body |\nlibrary MessageLib {\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MemViewLib for bytes;\n    using HeaderLib for MemView;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_HEADER = 0;\n    uint256 private constant OFFSET_BODY = OFFSET_HEADER + HEADER_LENGTH;\n\n    // ══════════════════════════════════════════════════ MESSAGE ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns formatted message with provided fields.\n     * @param header_   Encoded general routing information for the message\n     * @param body_     Formatted payload (according to flag) with message body\n     * @return Formatted message\n     */\n    function formatMessage(Header header_, bytes memory body_) internal pure returns (bytes memory) {\n        return abi.encodePacked(header_, body_);\n    }\n\n    /**\n     * @notice Returns a Message view over for the given payload.\n     * @dev Will revert if the payload is not a message payload.\n     */\n    function castToMessage(bytes memory payload) internal pure returns (Message) {\n        return castToMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Message view.\n     * @dev Will revert if the memory view is not over a message payload.\n     */\n    function castToMessage(MemView memView) internal pure returns (Message) {\n        if (!isMessage(memView)) revert UnformattedMessage();\n        return Message.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Message.\n     */\n    function isMessage(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Check if headers exist in the payload\n        if (length \u003c OFFSET_BODY) return false;\n        // Check that Header is valid\n        uint256 paddedHeader = _header(memView);\n        if (!HeaderLib.isHeader(paddedHeader)) return false;\n        // Check that body is formatted according to the flag\n        // Only Base/Manager message flags exist\n        if (HeaderLib.wrapPadded(paddedHeader).flag() == MessageFlag.Base) {\n            // Check if body is a formatted base message\n            return _body(memView).isBaseMessage();\n        } else {\n            // Check if body is a formatted calldata for AgentManager call\n            return _body(memView).isCallData();\n        }\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Message message) internal pure returns (MemView) {\n        return MemView.wrap(Message.unwrap(message));\n    }\n\n    /// @notice Returns message's hash: a leaf to be inserted in the Merkle tree.\n    function leaf(Message message) internal pure returns (bytes32) {\n        // We hash header and body separately to make message proofs easier to verify\n        Header header_ = message.header();\n        // Only Base/Manager message flags exist\n        if (header_.flag() == MessageFlag.Base) {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToBaseMessage().leaf());\n        } else {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToCallData().leaf());\n        }\n    }\n\n    // ══════════════════════════════════════════════ MESSAGE SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns message's encoded header field.\n    function header(Message message) internal pure returns (Header) {\n        return HeaderLib.wrapPadded((message.unwrap().indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH})));\n    }\n\n    /// @notice Returns message's body field as an untyped memory view.\n    function body(Message message) internal pure returns (MemView) {\n        MemView memView = message.unwrap();\n        return _body(memView);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns message's padded header without checking that it is a valid header.\n    function _header(MemView memView) private pure returns (uint256) {\n        return memView.indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH});\n    }\n\n    /// @dev Returns an untyped memory view over the body field without checking\n    /// if the whole payload or the body are properly formatted.\n    function _body(MemView memView) private pure returns (MemView) {\n        return memView.sliceFrom({index_: OFFSET_BODY});\n    }\n}\n\n// contracts/base/AgentSecured.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for messaging contracts that are secured by the agent manager.\n * `AgentSecured` relies on `AgentManager` to provide the following functionality:\n * - Keep track of agents and their statuses.\n * - Pass agent-signed statements that were verified by the agent manager.\n * - These statements are considered valid indefinitely, unless the agent is disputed.\n * - Disputes are opened and resolved by the agent manager.\n * \u003e `AgentSecured` implementation should never use statements signed by agents that are disputed.\n */\nabstract contract AgentSecured is MessagingBase, IAgentSecured {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    address public immutable agentManager;\n\n    /// @inheritdoc IAgentSecured\n    address public immutable inbox;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    // (agent index =\u003e their dispute status: flag, openedAt, resolvedAt)\n    mapping(uint32 =\u003e DisputeStatus) internal _disputes;\n\n    /// @dev gap for upgrade safety\n    uint256[49] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    modifier onlyAgentManager() {\n        if (msg.sender != agentManager) revert CallerNotAgentManager();\n        _;\n    }\n\n    modifier onlyInbox() {\n        if (msg.sender != inbox) revert CallerNotInbox();\n        _;\n    }\n\n    constructor(string memory version_, uint32 synapseDomain_, address agentManager_, address inbox_)\n        MessagingBase(version_, synapseDomain_)\n    {\n        agentManager = agentManager_;\n        inbox = inbox_;\n    }\n\n    // ════════════════════════════════════════════ ONLY AGENT MANAGER ═════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external onlyAgentManager {\n        uint40 openedAt = ChainContext.blockTimestamp();\n        DisputeStatus memory status = DisputeStatus({flag: DisputeFlag.Pending, openedAt: openedAt, resolvedAt: 0});\n        _disputes[guardIndex] = status;\n        _disputes[notaryIndex] = status;\n    }\n\n    /// @inheritdoc IAgentSecured\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external onlyAgentManager {\n        // Update the dispute status of the slashed agent first.\n        uint40 resolvedAt = ChainContext.blockTimestamp();\n        _disputes[slashedIndex].flag = DisputeFlag.Slashed;\n        _disputes[slashedIndex].resolvedAt = resolvedAt;\n        // Mark the rival agent as not disputed, if there was an ongoing dispute.\n        if (rivalIndex != 0) {\n            _disputes[rivalIndex].flag = DisputeFlag.None;\n            _disputes[rivalIndex].resolvedAt = resolvedAt;\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function agentStatus(address agent) external view returns (AgentStatus memory) {\n        return _agentStatus(agent);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status) {\n        return _getAgent(index);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory) {\n        return _disputes[agentIndex];\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns status of the given agent: (flag, domain, index).\n    function _agentStatus(address agent) internal view returns (AgentStatus memory) {\n        return IAgentManager(agentManager).agentStatus(agent);\n    }\n\n    /// @dev Returns agent and their status for a given agent index. Returns zero values for non existing indexes.\n    function _getAgent(uint256 index) internal view returns (address agent, AgentStatus memory status) {\n        return IAgentManager(agentManager).getAgent(index);\n    }\n\n    /// @dev Checks if a Dispute exists for the given Notary. This function returns true, if\n    /// Notary is in ongoing Dispute, or if Dispute was resolved not in Notary's favor.\n    /// In both cases we can't trust Notary's data.\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeExists(uint32 notaryIndex) internal view returns (bool) {\n        return _disputes[notaryIndex].flag != DisputeFlag.None;\n    }\n\n    /// @dev Checks if a Notary recently won a Dispute and is still in the \"post-dispute\" timeout period.\n    /// In this period we still can't trust Notary's data, though we can optimistically assume that\n    /// that the data will be correct after the timeout (assuming no new Disputes are opened).\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeTimeout(uint32 notaryIndex) internal view returns (bool) {\n        DisputeStatus memory status = _disputes[notaryIndex];\n        // Exit early if Notary is in ongoing Dispute / slashed.\n        if (status.flag != DisputeFlag.None) return false;\n        // Check if Notary has been in any Dispute at all.\n        if (status.openedAt == 0) return false;\n        // Otherwise check if the Dispute timeout is still active.\n        return block.timestamp \u003c status.resolvedAt + DISPUTE_TIMEOUT_NOTARY;\n    }\n}\n\n// contracts/hubs/StateHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StateHub` is a parent contract for `Origin`. It is responsible for the following:\n/// - Keeping track of the historical Origin Merkle Tree containing all the message hashes.\n/// - Keeping track of the historical Origin States, as well as verifying their validity.\nabstract contract StateHub is AgentSecured, StateHubEvents, IStateHub {\n    using SafeCast for uint256;\n    using StateLib for bytes;\n\n    struct OriginState {\n        uint40 blockNumber;\n        uint40 timestamp;\n        GasData gasData;\n    }\n    // Bits left for tight packing: 80\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Historical Merkle Tree\n    /// Note: Takes two storage slots\n    HistoricalTree private _tree;\n\n    /// @dev All historical contract States\n    OriginState[] private _originStates;\n\n    /// @dev gap for upgrade safety\n    uint256[47] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IStateHub\n    function isValidState(bytes memory statePayload) external view returns (bool isValid) {\n        // This will revert if payload is not a formatted state\n        State state = statePayload.castToState();\n        return _isValidState(state);\n    }\n\n    /// @inheritdoc IStateHub\n    function statesAmount() external view returns (uint256) {\n        return _originStates.length;\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestLatestState() external view returns (bytes memory stateData) {\n        // This never underflows, assuming the contract was initialized\n        return suggestState(_nextNonce() - 1);\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestState(uint32 nonce) public view returns (bytes memory stateData) {\n        // This will revert if nonce is out of range\n        bytes32 root = _tree.root(nonce);\n        return _formatOriginState(_originStates[nonce], root, localDomain, nonce);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Initializes the saved states list by inserting a state for an empty Merkle Tree.\n    function _initializeStates() internal {\n        // This should only be called once, when the contract is initialized\n        // This will revert if _tree.roots is non-empty\n        bytes32 savedRoot = _tree.initializeRoots();\n        // Save root for empty merkle _tree with block number and timestamp of initialization\n        _saveState(savedRoot, _toOriginState());\n    }\n\n    /// @dev Inserts leaf into the Merkle Tree and saves the updated origin State.\n    function _insertAndSave(bytes32 leaf) internal {\n        bytes32 newRoot = _tree.insert(leaf);\n        _saveState(newRoot, _toOriginState());\n    }\n\n    /// @dev Saves an updated state of the Origin contract\n    function _saveState(bytes32 root, OriginState memory state) internal {\n        uint32 nonce = _nextNonce();\n        _originStates.push(state);\n        // Emit event with raw state data\n        emit StateSaved(_formatOriginState(state, root, localDomain, nonce));\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns nonce of the next sent message: the amount of saved States so far.\n    /// This always equals to \"total amount of sent messages\" plus 1.\n    function _nextNonce() internal view returns (uint32) {\n        // TODO: consider using more than 32 bits for origin nonces\n        return _originStates.length.toUint32();\n    }\n\n    /// @dev Checks if a state is valid, i.e. if it matches the historical one.\n    /// Reverts, if state refers to another Origin contract.\n    function _isValidState(State state) internal view returns (bool) {\n        // Check if state refers to this contract\n        if (state.origin() != localDomain) revert IncorrectOriginDomain();\n        // Check if nonce exists\n        uint32 nonce = state.nonce();\n        if (nonce \u003e= _originStates.length) return false;\n        // Check if state root matches the historical one\n        if (state.root() != _tree.root(nonce)) return false;\n        // Check if state metadata matches the historical one\n        return _areEqual(state, _originStates[nonce]);\n    }\n\n    // ═════════════════════════════════════════════ STRUCT FORMATTING ═════════════════════════════════════════════════\n\n    /// @dev Returns a formatted payload for a stored OriginState.\n    function _formatOriginState(OriginState memory originState, bytes32 root, uint32 origin, uint32 nonce)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return StateLib.formatState({\n            root_: root,\n            origin_: origin,\n            nonce_: nonce,\n            blockNumber_: originState.blockNumber,\n            timestamp_: originState.timestamp,\n            gasData_: originState.gasData\n        });\n    }\n\n    /// @dev Child contract should implement the logic for getting the current gas data from the gas oracle\n    /// to be saved as part of the Origin State.\n    // solhint-disable-next-line ordering\n    function _fetchGasData() internal view virtual returns (GasData);\n\n    /// @dev Returns a OriginState struct to save in the contract.\n    function _toOriginState() internal view returns (OriginState memory originState) {\n        originState.blockNumber = ChainContext.blockNumber();\n        originState.timestamp = ChainContext.blockTimestamp();\n        originState.gasData = _fetchGasData();\n    }\n\n    /// @dev Checks that a state and its Origin representation are equal.\n    function _areEqual(State state, OriginState memory originState) internal pure returns (bool) {\n        return state.blockNumber() == originState.blockNumber \u0026\u0026 state.timestamp() == originState.timestamp;\n    }\n}\n\n// contracts/Origin.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Origin` contract is used for sending messages to remote chains. It is done\n/// by inserting the message hashes into the Origin Merkle, which makes it possible to\n/// prove that message was sent using the Merkle proof against the Origin Merkle Root. This essentially\n/// compresses the list of messages into a single 32-byte value that needs to be stored on the destination chain.\n/// `Origin` is responsible for the following:\n/// - Formatting the sent message payloads, and inserting their hashes into the Origin Merkle Tree.\n/// - Keeping track of its own historical states (see parent contract `StateHub`).\n/// - Enforcing minimum tip values for sent base messages based on the provided execution requests.\n/// - Distributing the collected tips upon request from a local `AgentManager` contract.\ncontract Origin is StateHub, OriginEvents, InterfaceOrigin {\n    using MemViewLib for bytes;\n    using MessageLib for bytes;\n    using TipsLib for bytes;\n    using TypeCasts for address;\n\n    address public immutable gasOracle;\n\n    modifier onlyRemoteDestination(uint32 destination) {\n        if (destination == localDomain) revert IncorrectDestinationDomain();\n        _;\n    }\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_, address gasOracle_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {\n        gasOracle = gasOracle_;\n    }\n\n    /// @notice Initializes Origin contract:\n    /// - msg.sender is set as contract owner\n    /// - State of \"empty merkle tree\" is saved\n    function initialize() external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize \"states\": state of an \"empty merkle tree\" is saved\n        _initializeStates();\n    }\n\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable onlyRemoteDestination(destination) returns (uint32 messageNonce, bytes32 messageHash) {\n        // Check that content is not too large\n        if (content.length \u003e MAX_CONTENT_BYTES) revert ContentLengthTooBig();\n        // This will revert if msg.value is lower than value of minimum tips\n        Tips tips = _getMinimumTips(destination, paddedRequest, content.length).matchValue(msg.value);\n        Request request = RequestLib.wrapPadded(paddedRequest);\n        // Format the BaseMessage body\n        bytes memory body = BaseMessageLib.formatBaseMessage({\n            sender_: msg.sender.addressToBytes32(),\n            recipient_: recipient,\n            tips_: tips,\n            request_: request,\n            content_: content\n        });\n        // Send the message\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Base, body);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        onlyAgentManager\n        onlyRemoteDestination(destination)\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // AgentManager (checked via modifier) is responsible for constructing the calldata payload correctly.\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Manager, payload);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function withdrawTips(address recipient, uint256 amount) external onlyAgentManager {\n        if (address(this).balance \u003c amount) revert InsufficientEthBalance();\n        (bool success,) = recipient.call{value: amount}(\"\");\n        if (!success) revert EthTransferFailed();\n        emit TipWithdrawalCompleted(recipient, amount);\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue)\n    {\n        return _getMinimumTips(destination, paddedRequest, contentLength).value();\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Sends the given message to the specified destination. Message hash is inserted\n    /// into the Origin Merkle Tree, which will enable message execution on destination chain.\n    function _sendMessage(uint32 destination, uint32 optimisticPeriod, MessageFlag flag, bytes memory body)\n        internal\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // Format the message header\n        messageNonce = _nextNonce();\n        Header header = flag.encodeHeader({\n            origin_: localDomain,\n            nonce_: messageNonce,\n            destination_: destination,\n            optimisticPeriod_: optimisticPeriod\n        });\n        // Format the full message payload\n        bytes memory msgPayload = MessageLib.formatMessage(header, body);\n        // Insert new leaf into the Origin Merkle Tree and save the updated state\n        messageHash = msgPayload.castToMessage().leaf();\n        _insertAndSave(messageHash);\n        // Emit event with message information\n        emit Sent(messageHash, messageNonce, destination, msgPayload);\n        // Update the gas oracle data. We do this after the provided tips are checked so that\n        // the provided message is sent in the event that the gas oracle data is updated to a higher value.\n        InterfaceGasOracle(gasOracle).updateGasData(destination);\n        // TODO: consider doing this before the message is sent, while adjusting GasOracle.getMinimumTips() to\n        // use the pending gas oracle data.\n    }\n\n    /// @dev Returns the minimum tips for sending a message to the given destination with the given request and content.\n    function _getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        internal\n        view\n        returns (Tips)\n    {\n        return\n            TipsLib.wrapPadded(InterfaceGasOracle(gasOracle).getMinimumTips(destination, paddedRequest, contentLength));\n    }\n\n    /// @dev Gets the current gas data from the gas oracle to be saved as part of the Origin State.\n    function _fetchGasData() internal view override returns (GasData) {\n        return GasDataLib.wrapGasData(InterfaceGasOracle(gasOracle).getGasData());\n    }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"167869:6743:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;167869:6743:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"167869:6743:0:-:0;;;;;;;;","abiDefinition":[],"userDoc":{"kind":"user","methods":{},"notice":"# Tips Library for formatting _the tips part_ of _the base messages_. ## How the tips are awarded Tips are paid for sending a base message, and are split across all the agents that made the message execution on destination chain possible. ### Summit tips Split between:     - Guard posting a snapshot with state ST_G for the origin chain.     - Notary posting a snapshot SN_N using ST_G. This creates attestation A.     - Notary posting a message receipt after it is executed on destination chain. ### Attestation tips Paid to:     - Notary posting attestation A to destination chain. ### Execution tips Paid to:     - First executor performing a valid execution attempt (correct proofs, optimistic period over),      using attestation A to prove message inclusion on origin chain, whether the recipient reverted or not. ### Delivery tips. Paid to:     - Executor who successfully executed the message on destination chain. ## Tips encoding - Tips occupy a single storage word, and thus are stored on stack instead of being stored in memory. - The actual tip values should be determined by multiplying stored values by divided by TIPS_MULTIPLIER=2**32. - Tips are packed into a single word of storage, while allowing real values up to ~8*10**28 for every tip category. \u003e The only downside is that the \"real tip values\" are now multiplies of ~4*10**9, which should be fine even for the chains with the most expensive gas currency. # Tips stack layout (from highest bits to lowest) | Position   | Field          | Type   | Bytes | Description                                                | | ---------- | -------------- | ------ | ----- | ---------------------------------------------------------- | | (032..024] | summitTip      | uint64 | 8     | Tip for agents interacting with Summit contract            | | (024..016] | attestationTip | uint64 | 8     | Tip for Notary posting attestation to Destination contract | | (016..008] | executionTip   | uint64 | 8     | Tip for valid execution attempt on destination chain       | | (008..000] | deliveryTip    | uint64 | 8     | Tip for successful message delivery on destination chain   |","version":1},"developerDoc":{"kind":"dev","methods":{},"stateVariables":{"SHIFT_ATTESTATION_TIP":{"details":"Amount of bits to shift to attestationTip field"},"SHIFT_EXECUTION_TIP":{"details":"Amount of bits to shift to executionTip field"},"SHIFT_SUMMIT_TIP":{"details":"Amount of bits to shift to summitTip field"}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"stateVariables\":{\"SHIFT_ATTESTATION_TIP\":{\"details\":\"Amount of bits to shift to attestationTip field\"},\"SHIFT_EXECUTION_TIP\":{\"details\":\"Amount of bits to shift to executionTip field\"},\"SHIFT_SUMMIT_TIP\":{\"details\":\"Amount of bits to shift to summitTip field\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"# Tips Library for formatting _the tips part_ of _the base messages_. ## How the tips are awarded Tips are paid for sending a base message, and are split across all the agents that made the message execution on destination chain possible. ### Summit tips Split between:     - Guard posting a snapshot with state ST_G for the origin chain.     - Notary posting a snapshot SN_N using ST_G. This creates attestation A.     - Notary posting a message receipt after it is executed on destination chain. ### Attestation tips Paid to:     - Notary posting attestation A to destination chain. ### Execution tips Paid to:     - First executor performing a valid execution attempt (correct proofs, optimistic period over),      using attestation A to prove message inclusion on origin chain, whether the recipient reverted or not. ### Delivery tips. Paid to:     - Executor who successfully executed the message on destination chain. ## Tips encoding - Tips occupy a single storage word, and thus are stored on stack instead of being stored in memory. - The actual tip values should be determined by multiplying stored values by divided by TIPS_MULTIPLIER=2**32. - Tips are packed into a single word of storage, while allowing real values up to ~8*10**28 for every tip category. \u003e The only downside is that the \\\"real tip values\\\" are now multiplies of ~4*10**9, which should be fine even for the chains with the most expensive gas currency. # Tips stack layout (from highest bits to lowest) | Position   | Field          | Type   | Bytes | Description                                                | | ---------- | -------------- | ------ | ----- | ---------------------------------------------------------- | | (032..024] | summitTip      | uint64 | 8     | Tip for agents interacting with Summit contract            | | (024..016] | attestationTip | uint64 | 8     | Tip for Notary posting attestation to Destination contract | | (016..008] | executionTip   | uint64 | 8     | Tip for valid execution attempt on destination chain       | | (008..000] | deliveryTip    | uint64 | 8     | Tip for successful message delivery on destination chain   |\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Origin.sol\":\"TipsLib\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Origin.sol\":{\"keccak256\":\"0x96775924f147f3d1f8df8cdf56731fe52a15af8d8e12e608efb8158c112b18cd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e642a27f5fab3c62b4c02e9754e9e42b1cf2e5381dbea9d3d106d23b7772ebe6\",\"dweb:/ipfs/QmUwn7ZyBvPkjnMuK8ZMSexBUdNQnVtxwyoAyT4DXLQjra\"]}},\"version\":1}"},"hashes":{}},"solidity/Origin.sol:TypeCasts":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220a8039d6202eb5e0aa6f21826393b0e41b0390b1bd8d656852cfa3f7187f037ca64736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220a8039d6202eb5e0aa6f21826393b0e41b0390b1bd8d656852cfa3f7187f037ca64736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/OriginEvents.sol\n\n/// @notice A collection of events emitted by the Origin contract\nabstract contract OriginEvents {\n    /**\n     * @notice Emitted when a new message is sent.\n     * @param messageHash   Hash of message; the leaf inserted to the Merkle tree for the message\n     * @param nonce         Nonce of sent message (starts from 1)\n     * @param destination   Destination domain\n     * @param message       Raw bytes of message\n     */\n    event Sent(bytes32 indexed messageHash, uint32 indexed nonce, uint32 indexed destination, bytes message);\n\n    /**\n     * @notice Emitted when a tip withdrawal is completed.\n     * @param actor     Actor address\n     * @param tip       Tip value, denominated in local domain's wei\n     */\n    event TipWithdrawalCompleted(address actor, uint256 tip);\n}\n\n// contracts/events/StateHubEvents.sol\n\n/// @notice A collection of events emitted by the StateHub contract\nabstract contract StateHubEvents {\n    /**\n     * @notice Emitted when a new Origin State is saved after a message was sent.\n     * @param state     Raw payload with state data\n     */\n    event StateSaved(bytes state);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n    /**\n     * @notice Check that a given state is valid: matches the historical state of Origin contract.\n     * Note: any Agent including an invalid state in their snapshot will be slashed\n     * upon providing the snapshot and agent signature for it to Origin contract.\n     * @dev Will revert if any of these is true:\n     *  - State payload is not properly formatted.\n     * @param statePayload      Raw payload with state data\n     * @return isValid          Whether the provided state is valid\n     */\n    function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns the amount of saved states so far.\n     * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n     */\n    function statesAmount() external view returns (uint256);\n\n    /**\n     * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @return statePayload     Raw payload with the latest state data\n     */\n    function suggestLatestState() external view returns (bytes memory statePayload);\n\n    /**\n     * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @param nonce             Historical nonce to form a state\n     * @return statePayload     Raw payload with historical state data\n     */\n    function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/InterfaceGasOracle.sol\n\ninterface InterfaceGasOracle {\n    /**\n     * @notice Fetches the latest gas data for the chain from `Destination` contract,\n     * and uses it to update the oracle values for the requested chain.\n     * @param domain    Domain to update the gas data for\n     */\n    function updateGasData(uint32 domain) external;\n\n    /**\n     * @notice Returns the gas data for the local chain.\n     */\n    function getGasData() external view returns (uint256 paddedGasData);\n\n    /**\n     * @notice Returns the gas data for the given domain, in the decoded format.\n     * @param domain        Domain of chain to get gas data for\n     * @return gasPrice     Gas price for the chain (in Wei per gas unit)\n     * @return dataPrice    Calldata price (in Wei per byte of content)\n     * @return execBuffer   Tx fee safety buffer for message execution (in Wei)\n     * @return amortAttCost Amortized cost for attestation submission (in Wei)\n     * @return etherPrice   Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n     * @return markup       Markup for the message execution (in BWAD)\n     */\n    function getDecodedGasData(uint32 domain)\n        external\n        view\n        returns (\n            uint256 gasPrice,\n            uint256 dataPrice,\n            uint256 execBuffer,\n            uint256 amortAttCost,\n            uint256 etherPrice,\n            uint256 markup\n        );\n\n    /**\n     * @notice Returns the minimum tips for sending a message to a given destination.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return paddedTips       Padded encoded minimum tips information\n     */\n    function getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 paddedTips);\n}\n\n// contracts/interfaces/InterfaceOrigin.sol\n\ninterface InterfaceOrigin {\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /**\n     * @notice Send a message to the recipient located on destination domain.\n     * @dev Recipient has to conform to IMessageRecipient interface, otherwise message won't be delivered.\n     * Will revert if any of these is true:\n     * - `destination` is equal to contract's local domain\n     * - `content` length is greater than `MAX_CONTENT_BYTES`\n     * - `msg.value` is lower than value of minimum tips for the given message\n     * @param destination           Domain of destination chain\n     * @param recipient             Address of recipient on destination chain as bytes32\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param paddedRequest         Padded encoded message execution request on destination chain\n     * @param content               Raw bytes content of message\n     * @return messageNonce         Nonce of the sent message\n     * @return messageHash          Hash of the sent message\n     */\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable returns (uint32 messageNonce, bytes32 messageHash);\n\n    /**\n     * @notice Send a manager message to the destination domain.\n     * @dev This could only be called by AgentManager, which takes care of encoding the calldata payload.\n     * Note: (msgOrigin, proofMaturity) security args will be added to payload on the destination chain\n     * so that the AgentManager could verify where the Manager Message came from and how mature is the proof.\n     * Note: function is not payable, as no tips are required for sending a manager message.\n     * Will revert if `destination` is equal to contract's local domain.\n     * @param destination           Domain of destination chain\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param payload               Payload for calling AgentManager on destination chain (with extra security args)\n     */\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        returns (uint32 messageNonce, bytes32 messageHash);\n\n    // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Withdraws locked base message tips to the recipient.\n     * @dev Could only be called by a local AgentManager.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function withdrawTips(address recipient, uint256 amount) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the minimum tips value for sending a message to a given destination.\n     * @dev Using at least `tipsValue` as `msg.value` for `sendBaseMessage()`\n     * will guarantee that the message will be accepted.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return tipsValue        Minimum tips value for a message to be accepted\n     */\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue);\n}\n\n// contracts/libs/Constants.sol\n\n// Here we define common constants to enable their easier reusing later.\n\n// ══════════════════════════════════ MERKLE ═══════════════════════════════════\n/// @dev Height of the Agent Merkle Tree\nuint256 constant AGENT_TREE_HEIGHT = 32;\n/// @dev Height of the Origin Merkle Tree\nuint256 constant ORIGIN_TREE_HEIGHT = 32;\n/// @dev Height of the Snapshot Merkle Tree. Allows up to 64 leafs, e.g. up to 32 states\nuint256 constant SNAPSHOT_TREE_HEIGHT = 6;\n// ══════════════════════════════════ STRUCTS ══════════════════════════════════\n/// @dev See Attestation.sol: (bytes32,bytes32,uint32,uint40,uint40): 32+32+4+5+5\nuint256 constant ATTESTATION_LENGTH = 78;\n/// @dev See GasData.sol: (uint16,uint16,uint16,uint16,uint16,uint16): 2+2+2+2+2+2\nuint256 constant GAS_DATA_LENGTH = 12;\n/// @dev See Receipt.sol: (uint32,uint32,bytes32,bytes32,uint8,address,address,address): 4+4+32+32+1+20+20+20\nuint256 constant RECEIPT_LENGTH = 133;\n/// @dev See State.sol: (bytes32,uint32,uint32,uint40,uint40,GasData): 32+4+4+5+5+len(GasData)\nuint256 constant STATE_LENGTH = 50 + GAS_DATA_LENGTH;\n/// @dev Maximum amount of states in a single snapshot. Each state produces two leafs in the tree\nuint256 constant SNAPSHOT_MAX_STATES = 1 \u003c\u003c (SNAPSHOT_TREE_HEIGHT - 1);\n// ══════════════════════════════════ MESSAGE ══════════════════════════════════\n/// @dev See Header.sol: (uint8,uint32,uint32,uint32,uint32): 1+4+4+4+4\nuint256 constant HEADER_LENGTH = 17;\n/// @dev See Request.sol: (uint96,uint64,uint32): 12+8+4\nuint256 constant REQUEST_LENGTH = 24;\n/// @dev See Tips.sol: (uint64,uint64,uint64,uint64): 8+8+8+8\nuint256 constant TIPS_LENGTH = 32;\n/// @dev The amount of discarded last bits when encoding tip values\nuint256 constant TIPS_GRANULARITY = 32;\n/// @dev Tip values could be only the multiples of TIPS_MULTIPLIER\nuint256 constant TIPS_MULTIPLIER = 1 \u003c\u003c TIPS_GRANULARITY;\n// ══════════════════════════════ STATEMENT SALTS ══════════════════════════════\n/// @dev Salts for signing various statements\nbytes32 constant ATTESTATION_VALID_SALT = keccak256(\"ATTESTATION_VALID_SALT\");\nbytes32 constant ATTESTATION_INVALID_SALT = keccak256(\"ATTESTATION_INVALID_SALT\");\nbytes32 constant RECEIPT_VALID_SALT = keccak256(\"RECEIPT_VALID_SALT\");\nbytes32 constant RECEIPT_INVALID_SALT = keccak256(\"RECEIPT_INVALID_SALT\");\nbytes32 constant SNAPSHOT_VALID_SALT = keccak256(\"SNAPSHOT_VALID_SALT\");\nbytes32 constant STATE_INVALID_SALT = keccak256(\"STATE_INVALID_SALT\");\n// ═════════════════════════════════ PROTOCOL ══════════════════════════════════\n/// @dev Optimistic period for new agent roots in LightManager\nuint32 constant AGENT_ROOT_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Timeout between the agent root could be proposed and resolved in LightManager\nuint32 constant AGENT_ROOT_PROPOSAL_TIMEOUT = 12 hours;\nuint32 constant BONDING_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Amount of time that the Notary will not be considered active after they won a dispute\nuint32 constant DISPUTE_TIMEOUT_NOTARY = 12 hours;\n/// @dev Amount of time without fresh data from Notaries before contract owner can resolve stuck disputes manually\nuint256 constant FRESH_DATA_TIMEOUT = 4 hours;\n/// @dev Maximum bytes per message = 2 KiB (somewhat arbitrarily set to begin)\nuint256 constant MAX_CONTENT_BYTES = 2 * 2 ** 10;\n/// @dev Maximum value for the summit tip that could be set in GasOracle\nuint256 constant MAX_SUMMIT_TIP = 0.01 ether;\n\n// contracts/libs/Errors.sol\n\n// ══════════════════════════════ INVALID CALLER ═══════════════════════════════\n\nerror CallerNotAgentManager();\nerror CallerNotDestination();\nerror CallerNotInbox();\nerror CallerNotSummit();\n\n// ══════════════════════════════ INCORRECT DATA ═══════════════════════════════\n\nerror IncorrectAttestation();\nerror IncorrectAgentDomain();\nerror IncorrectAgentIndex();\nerror IncorrectAgentProof();\nerror IncorrectAgentRoot();\nerror IncorrectDataHash();\nerror IncorrectDestinationDomain();\nerror IncorrectOriginDomain();\nerror IncorrectSnapshotProof();\nerror IncorrectSnapshotRoot();\nerror IncorrectState();\nerror IncorrectStatesAmount();\nerror IncorrectTipsProof();\nerror IncorrectVersionLength();\n\nerror IncorrectNonce();\nerror IncorrectSender();\nerror IncorrectRecipient();\n\nerror FlagOutOfRange();\nerror IndexOutOfRange();\nerror NonceOutOfRange();\n\nerror OutdatedNonce();\n\nerror UnformattedAttestation();\nerror UnformattedAttestationReport();\nerror UnformattedBaseMessage();\nerror UnformattedCallData();\nerror UnformattedCallDataPrefix();\nerror UnformattedMessage();\nerror UnformattedReceipt();\nerror UnformattedReceiptReport();\nerror UnformattedSignature();\nerror UnformattedSnapshot();\nerror UnformattedState();\nerror UnformattedStateReport();\n\n// ═══════════════════════════════ MERKLE TREES ════════════════════════════════\n\nerror LeafNotProven();\nerror MerkleTreeFull();\nerror NotEnoughLeafs();\nerror TreeHeightTooLow();\n\n// ═════════════════════════════ OPTIMISTIC PERIOD ═════════════════════════════\n\nerror BaseClientOptimisticPeriod();\nerror MessageOptimisticPeriod();\nerror SlashAgentOptimisticPeriod();\nerror WithdrawTipsOptimisticPeriod();\nerror ZeroProofMaturity();\n\n// ═══════════════════════════════ AGENT MANAGER ═══════════════════════════════\n\nerror AgentNotGuard();\nerror AgentNotNotary();\n\nerror AgentCantBeAdded();\nerror AgentNotActive();\nerror AgentNotActiveNorUnstaking();\nerror AgentNotFraudulent();\nerror AgentNotUnstaking();\nerror AgentUnknown();\n\nerror AgentRootNotProposed();\nerror AgentRootTimeoutNotOver();\n\nerror NotStuck();\n\nerror DisputeAlreadyResolved();\nerror DisputeNotOpened();\nerror DisputeTimeoutNotOver();\nerror GuardInDispute();\nerror NotaryInDispute();\n\nerror MustBeSynapseDomain();\nerror SynapseDomainForbidden();\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\nerror AlreadyExecuted();\nerror AlreadyFailed();\nerror DuplicatedSnapshotRoot();\nerror IncorrectMagicValue();\nerror GasLimitTooLow();\nerror GasSuppliedTooLow();\n\n// ══════════════════════════════════ ORIGIN ═══════════════════════════════════\n\nerror ContentLengthTooBig();\nerror EthTransferFailed();\nerror InsufficientEthBalance();\n\n// ════════════════════════════════ GAS ORACLE ═════════════════════════════════\n\nerror LocalGasDataNotSet();\nerror RemoteGasDataNotSet();\n\n// ═══════════════════════════════════ TIPS ════════════════════════════════════\n\nerror SummitTipTooHigh();\nerror TipsClaimMoreThanEarned();\nerror TipsClaimZero();\nerror TipsOverflow();\nerror TipsValueTooLow();\n\n// ════════════════════════════════ MEMORY VIEW ════════════════════════════════\n\nerror IndexedTooMuch();\nerror ViewOverrun();\nerror OccupiedMemory();\nerror UnallocatedMemory();\nerror PrecompileOutOfGas();\n\n// ═════════════════════════════════ MULTICALL ═════════════════════════════════\n\nerror MulticallFailed();\n\n// contracts/libs/TypeCasts.sol\n\nlibrary TypeCasts {\n    // alignment preserving cast\n    function addressToBytes32(address addr) internal pure returns (bytes32) {\n        return bytes32(uint256(uint160(addr)));\n    }\n\n    // alignment preserving cast\n    function bytes32ToAddress(bytes32 buf) internal pure returns (address) {\n        return address(uint160(uint256(buf)));\n    }\n}\n\n// contracts/libs/stack/Number.sol\n\n/// Number is a compact representation of uint256, that is fit into 16 bits\n/// with the maximum relative error under 0.4%.\ntype Number is uint16;\n\nusing NumberLib for Number global;\n\n/// # Number\n/// Library for compact representation of uint256 numbers.\n/// - Number is stored using mantissa and exponent, each occupying 8 bits.\n/// - Numbers under 2**8 are stored as `mantissa` with `exponent = 0xFF`.\n/// - Numbers at least 2**8 are approximated as `(256 + mantissa) \u003c\u003c exponent`\n/// \u003e - `0 \u003c= mantissa \u003c 256`\n/// \u003e - `0 \u003c= exponent \u003c= 247` (`256 * 2**248` doesn't fit into uint256)\n/// # Number stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type  | Bytes |\n/// | ---------- | -------- | ----- | ----- |\n/// | (002..001] | mantissa | uint8 | 1     |\n/// | (001..000] | exponent | uint8 | 1     |\n\nlibrary NumberLib {\n    /// @dev Amount of bits to shift to mantissa field\n    uint16 private constant SHIFT_MANTISSA = 8;\n\n    /// @notice For bwad math (binary wad) we use 2**64 as \"wad\" unit.\n    /// @dev We are using not using 10**18 as wad, because it is not stored precisely in NumberLib.\n    uint256 internal constant BWAD_SHIFT = 64;\n    uint256 internal constant BWAD = 1 \u003c\u003c BWAD_SHIFT;\n    /// @notice ~0.1% in bwad units.\n    uint256 internal constant PER_MILLE_SHIFT = BWAD_SHIFT - 10;\n    uint256 internal constant PER_MILLE = 1 \u003c\u003c PER_MILLE_SHIFT;\n\n    /// @notice Compresses uint256 number into 16 bits.\n    function compress(uint256 value) internal pure returns (Number) {\n        // Find `msb` such as `2**msb \u003c= value \u003c 2**(msb + 1)`\n        uint256 msb = mostSignificantBit(value);\n        // We want to preserve 9 bits of precision.\n        // The highest bit is always 1, so we can skip it.\n        // The remaining 8 highest bits are stored as mantissa.\n        if (msb \u003c 8) {\n            // Value is less than 2**8, so we can use value as mantissa with \"-1\" exponent.\n            return _encode(uint8(value), 0xFF);\n        } else {\n            // We use `msb - 8` as exponent otherwise. Note that `exponent \u003e= 0`.\n            unchecked {\n                uint256 exponent = msb - 8;\n                // Shifting right by `msb-8` bits will shift the \"remaining 8 highest bits\" into the 8 lowest bits.\n                // uint8() will truncate the highest bit.\n                return _encode(uint8(value \u003e\u003e exponent), uint8(exponent));\n            }\n        }\n    }\n\n    /// @notice Decompresses 16 bits number into uint256.\n    /// @dev The outcome is an approximation of the original number: `(value - value / 256) \u003c number \u003c= value`.\n    function decompress(Number number) internal pure returns (uint256 value) {\n        // Isolate 8 highest bits as the mantissa.\n        uint256 mantissa = Number.unwrap(number) \u003e\u003e SHIFT_MANTISSA;\n        // This will truncate the highest bits, leaving only the exponent.\n        uint256 exponent = uint8(Number.unwrap(number));\n        if (exponent == 0xFF) {\n            return mantissa;\n        } else {\n            unchecked {\n                return (256 + mantissa) \u003c\u003c (exponent);\n            }\n        }\n    }\n\n    /// @dev Returns the most significant bit of `x`\n    /// https://solidity-by-example.org/bitwise/\n    function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\n        // To find `msb` we determine it bit by bit, starting from the highest one.\n        // `0 \u003c= msb \u003c= 255`, so we start from the highest bit, 1\u003c\u003c7 == 128.\n        // If `x` is at least 2**128, then the highest bit of `x` is at least 128.\n        // solhint-disable no-inline-assembly\n        assembly {\n            // `f` is set to 1\u003c\u003c7 if `x \u003e= 2**128` and to 0 otherwise.\n            let f := shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\n            // If `x \u003e= 2**128` then set `msb` highest bit to 1 and shift `x` right by 128.\n            // Otherwise, `msb` remains 0 and `x` remains unchanged.\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        // `x` is now at most 2**128 - 1. Continue the same way, the next highest bit is 1\u003c\u003c6 == 64.\n        assembly {\n            // `f` is set to 1\u003c\u003c6 if `x \u003e= 2**64` and to 0 otherwise.\n            let f := shl(6, gt(x, 0xFFFFFFFFFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c5 if `x \u003e= 2**32` and to 0 otherwise.\n            let f := shl(5, gt(x, 0xFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c4 if `x \u003e= 2**16` and to 0 otherwise.\n            let f := shl(4, gt(x, 0xFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c3 if `x \u003e= 2**8` and to 0 otherwise.\n            let f := shl(3, gt(x, 0xFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c2 if `x \u003e= 2**4` and to 0 otherwise.\n            let f := shl(2, gt(x, 0xF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c1 if `x \u003e= 2**2` and to 0 otherwise.\n            let f := shl(1, gt(x, 0x3))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1 if `x \u003e= 2**1` and to 0 otherwise.\n            let f := gt(x, 0x1)\n            msb := or(msb, f)\n        }\n    }\n\n    /// @dev Wraps (mantissa, exponent) pair into Number.\n    function _encode(uint8 mantissa, uint8 exponent) private pure returns (Number) {\n        // Casts below are upcasts, so they are safe.\n        return Number.wrap(uint16(mantissa) \u003c\u003c SHIFT_MANTISSA | uint16(exponent));\n    }\n}\n\n// contracts/libs/stack/Request.sol\n\n/// Request is encoded data with \"message execution request\".\ntype Request is uint192;\n\nusing RequestLib for Request global;\n\n/// Library for formatting _the request part_ of _the base messages_.\n/// - Request represents a message sender requirements for the message execution on the destination chain.\n/// - Request occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n/// \u003e gasDrop field is included for future compatibility and is ignored at the moment.\n///\n/// # Request stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type   | Bytes | Description                                          |\n/// | ---------- | -------- | ------ | ----- | ---------------------------------------------------- |\n/// | (024..012] | gasDrop  | uint96 | 12    | Minimum amount of gas token to drop to the recipient |\n/// | (012..004] | gasLimit | uint64 | 8     | Minimum amount of gas units to supply for execution  |\n/// | (004..000] | version  | uint32 | 4     | Base message version to pass to the recipient        |\n\nlibrary RequestLib {\n    /// @dev Amount of bits to shift to gasDrop field\n    uint192 private constant SHIFT_GAS_DROP = 12 * 8;\n    /// @dev Amount of bits to shift to gasLimit field\n    uint192 private constant SHIFT_GAS_LIMIT = 4 * 8;\n\n    /// @notice Returns an encoded request with the given fields\n    /// @param gasDrop_     Minimum amount of gas token to drop to the recipient (ignored at the moment)\n    /// @param gasLimit_    Minimum amount of gas units to supply for execution\n    /// @param version_     Base message version to pass to the recipient\n    function encodeRequest(uint96 gasDrop_, uint64 gasLimit_, uint32 version_) internal pure returns (Request) {\n        // Casts below are upcasts, so they are safe\n        return Request.wrap(uint192(gasDrop_) \u003c\u003c SHIFT_GAS_DROP | uint192(gasLimit_) \u003c\u003c SHIFT_GAS_LIMIT | version_);\n    }\n\n    /// @notice Wraps the padded encoded request into a Request-typed value.\n    /// @dev The \"padded\" request is simply an encoded request casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded requests\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedRequest) internal pure returns (Request) {\n        // Casting to uint192 will truncate the highest bits, which is the behavior we want\n        return Request.wrap(uint192(paddedRequest));\n    }\n\n    /// @notice Returns the requested of gas token to drop to the recipient.\n    function gasDrop(Request request) internal pure returns (uint96) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return uint96(Request.unwrap(request) \u003e\u003e SHIFT_GAS_DROP);\n    }\n\n    /// @notice Returns the requested minimum amount of gas units to supply for execution.\n    function gasLimit(Request request) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Request.unwrap(request) \u003e\u003e SHIFT_GAS_LIMIT);\n    }\n\n    /// @notice Returns the requested base message version to pass to the recipient.\n    function version(Request request) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Request.unwrap(request));\n    }\n}\n\n// node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        require(value \u003c= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        require(value \u003c= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        require(value \u003c= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value \u003c= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        require(value \u003c= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        require(value \u003c= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        require(value \u003c= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        require(value \u003c= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        require(value \u003c= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        require(value \u003c= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        require(value \u003c= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        require(value \u003c= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        require(value \u003c= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        require(value \u003c= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        require(value \u003c= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value \u003c= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        require(value \u003c= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        require(value \u003c= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        require(value \u003c= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value \u003c= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        require(value \u003c= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        require(value \u003c= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        require(value \u003c= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value \u003c= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        require(value \u003c= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        require(value \u003c= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        require(value \u003c= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value \u003c= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        require(value \u003c= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value \u003c= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value \u003c= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     *\n     * _Available since v3.0._\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value \u003e= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     *\n     * _Available since v3.0._\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value \u003c= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     *\n     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length \u003e 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance \u003e= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance \u003e= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length \u003e 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n\n// contracts/base/MultiCallable.sol\n\n/// @notice Collection of Multicall utilities. Fork of Multicall3:\n/// https://github.com/mds1/multicall/blob/master/src/Multicall3.sol\nabstract contract MultiCallable {\n    struct Call {\n        bool allowFailure;\n        bytes callData;\n    }\n\n    struct Result {\n        bool success;\n        bytes returnData;\n    }\n\n    /// @notice Aggregates a few calls to this contract into one multicall without modifying `msg.sender`.\n    function multicall(Call[] calldata calls) external returns (Result[] memory callResults) {\n        uint256 amount = calls.length;\n        callResults = new Result[](amount);\n        Call calldata call_;\n        for (uint256 i = 0; i \u003c amount;) {\n            call_ = calls[i];\n            Result memory result = callResults[i];\n            // We perform a delegate call to ourselves here. Delegate call does not modify `msg.sender`, so\n            // this will have the same effect as if `msg.sender` performed all the calls themselves one by one.\n            // solhint-disable-next-line avoid-low-level-calls\n            (result.success, result.returnData) = address(this).delegatecall(call_.callData);\n            // solhint-disable-next-line no-inline-assembly\n            assembly {\n                // Revert if the call fails and failure is not allowed\n                // `allowFailure := calldataload(call_)` and `success := mload(result)`\n                if iszero(or(calldataload(call_), mload(result))) {\n                    // Revert with `0x4d6a2328` (function selector for `MulticallFailed()`)\n                    mstore(0x00, 0x4d6a232800000000000000000000000000000000000000000000000000000000)\n                    revert(0x00, 0x04)\n                }\n            }\n            unchecked {\n                ++i;\n            }\n        }\n    }\n}\n\n// contracts/base/Version.sol\n\n/**\n * @title Versioned\n * @notice Version getter for contracts. Doesn't use any storage slots, meaning\n * it will never cause any troubles with the upgradeable contracts. For instance, this contract\n * can be added or removed from the inheritance chain without shifting the storage layout.\n */\nabstract contract Versioned {\n    /**\n     * @notice Struct that is mimicking the storage layout of a string with 32 bytes or less.\n     * Length is limited by 32, so the whole string payload takes two memory words:\n     * @param length    String length\n     * @param data      String characters\n     */\n    struct _ShortString {\n        uint256 length;\n        bytes32 data;\n    }\n\n    /// @dev Length of the \"version string\"\n    uint256 private immutable _length;\n    /// @dev Bytes representation of the \"version string\".\n    /// Strings with length over 32 are not supported!\n    bytes32 private immutable _data;\n\n    constructor(string memory version_) {\n        _length = bytes(version_).length;\n        if (_length \u003e 32) revert IncorrectVersionLength();\n        // bytes32 is left-aligned =\u003e this will store the byte representation of the string\n        // with the trailing zeroes to complete the 32-byte word\n        _data = bytes32(bytes(version_));\n    }\n\n    function version() external view returns (string memory versionString) {\n        // Load the immutable values to form the version string\n        _ShortString memory str = _ShortString(_length, _data);\n        // The only way to do this cast is doing some dirty assembly\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            versionString := str\n        }\n    }\n}\n\n// contracts/libs/ChainContext.sol\n\n/// @notice Library for accessing chain context variables as tightly packed integers.\n/// Messaging contracts should rely on this library for accessing chain context variables\n/// instead of doing the casting themselves.\nlibrary ChainContext {\n    using SafeCast for uint256;\n\n    /// @notice Returns the current block number as uint40.\n    /// @dev Reverts if block number is greater than 40 bits, which is not supposed to happen\n    /// until the block.timestamp overflows (assuming block time is at least 1 second).\n    function blockNumber() internal view returns (uint40) {\n        return block.number.toUint40();\n    }\n\n    /// @notice Returns the current block timestamp as uint40.\n    /// @dev Reverts if block timestamp is greater than 40 bits, which is\n    /// supposed to happen approximately in year 36835.\n    function blockTimestamp() internal view returns (uint40) {\n        return block.timestamp.toUint40();\n    }\n\n    /// @notice Returns the chain id as uint32.\n    /// @dev Reverts if chain id is greater than 32 bits, which is not\n    /// supposed to happen in production.\n    function chainId() internal view returns (uint32) {\n        return block.chainid.toUint32();\n    }\n}\n\n// contracts/libs/Structures.sol\n\n// Here we define common enums and structures to enable their easier reusing later.\n\n// ═══════════════════════════════ AGENT STATUS ════════════════════════════════\n\n/// @dev Potential statuses for the off-chain bonded agent:\n/// - Unknown: never provided a bond =\u003e signature not valid\n/// - Active: has a bond in BondingManager =\u003e signature valid\n/// - Unstaking: has a bond in BondingManager, initiated the unstaking =\u003e signature not valid\n/// - Resting: used to have a bond in BondingManager, successfully unstaked =\u003e signature not valid\n/// - Fraudulent: proven to commit fraud, value in Merkle Tree not updated =\u003e signature not valid\n/// - Slashed: proven to commit fraud, value in Merkle Tree was updated =\u003e signature not valid\n/// Unstaked agent could later be added back to THE SAME domain by staking a bond again.\n/// Honest agent: Unknown -\u003e Active -\u003e unstaking -\u003e Resting -\u003e Active ...\n/// Malicious agent: Unknown -\u003e Active -\u003e Fraudulent -\u003e Slashed\n/// Malicious agent: Unknown -\u003e Active -\u003e Unstaking -\u003e Fraudulent -\u003e Slashed\nenum AgentFlag {\n    Unknown,\n    Active,\n    Unstaking,\n    Resting,\n    Fraudulent,\n    Slashed\n}\n\n/// @notice Struct for storing an agent in the BondingManager contract.\nstruct AgentStatus {\n    AgentFlag flag;\n    uint32 domain;\n    uint32 index;\n}\n// 184 bits available for tight packing\n\nusing StructureUtils for AgentStatus global;\n\n/// @notice Potential statuses of an agent in terms of being in dispute\n/// - None: agent is not in dispute\n/// - Pending: agent is in unresolved dispute\n/// - Slashed: agent was in dispute that lead to agent being slashed\n/// Note: agent who won the dispute has their status reset to None\nenum DisputeFlag {\n    None,\n    Pending,\n    Slashed\n}\n\n/// @notice Struct for storing dispute status of an agent.\n/// @param flag         Dispute flag: None/Pending/Slashed.\n/// @param openedAt     Timestamp when the latest agent dispute was opened (zero if not opened).\n/// @param resolvedAt   Timestamp when the latest agent dispute was resolved (zero if not resolved).\nstruct DisputeStatus {\n    DisputeFlag flag;\n    uint40 openedAt;\n    uint40 resolvedAt;\n}\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\n/// @notice Struct representing the status of Destination contract.\n/// @param snapRootTime     Timestamp when latest snapshot root was accepted\n/// @param agentRootTime    Timestamp when latest agent root was accepted\n/// @param notaryIndex      Index of Notary who signed the latest agent root\nstruct DestinationStatus {\n    uint40 snapRootTime;\n    uint40 agentRootTime;\n    uint32 notaryIndex;\n}\n\n// ═══════════════════════════════ EXECUTION HUB ═══════════════════════════════\n\n/// @notice Potential statuses of the message in Execution Hub.\n/// - None: there hasn't been a valid attempt to execute the message yet\n/// - Failed: there was a valid attempt to execute the message, but recipient reverted\n/// - Success: there was a valid attempt to execute the message, and recipient did not revert\n/// Note: message can be executed until its status is Success\nenum MessageStatus {\n    None,\n    Failed,\n    Success\n}\n\nlibrary StructureUtils {\n    /// @notice Checks that Agent is Active\n    function verifyActive(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active) {\n            revert AgentNotActive();\n        }\n    }\n\n    /// @notice Checks that Agent is Unstaking\n    function verifyUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Unstaking) {\n            revert AgentNotUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Active or Unstaking\n    function verifyActiveUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active \u0026\u0026 status.flag != AgentFlag.Unstaking) {\n            revert AgentNotActiveNorUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Fraudulent\n    function verifyFraudulent(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Fraudulent) {\n            revert AgentNotFraudulent();\n        }\n    }\n\n    /// @notice Checks that Agent is not Unknown\n    function verifyKnown(AgentStatus memory status) internal pure {\n        if (status.flag == AgentFlag.Unknown) {\n            revert AgentUnknown();\n        }\n    }\n}\n\n// contracts/libs/memory/MemView.sol\n\n/// @dev MemView is an untyped view over a portion of memory to be used instead of `bytes memory`\ntype MemView is uint256;\n\n/// @dev Attach library functions to MemView\nusing MemViewLib for MemView global;\n\n/// @notice Library for operations with the memory views.\n/// Forked from https://github.com/summa-tx/memview-sol with several breaking changes:\n/// - The codebase is ported to Solidity 0.8\n/// - Custom errors are added\n/// - The runtime type checking is replaced with compile-time check provided by User-Defined Value Types\n///   https://docs.soliditylang.org/en/latest/types.html#user-defined-value-types\n/// - uint256 is used as the underlying type for the \"memory view\" instead of bytes29.\n///   It is wrapped into MemView custom type in order not to be confused with actual integers.\n/// - Therefore the \"type\" field is discarded, allowing to allocate 16 bytes for both view location and length\n/// - The documentation is expanded\n/// - Library functions unused by the rest of the codebase are removed\n//  - Very pretty code separators are added :)\nlibrary MemViewLib {\n    /// @notice Stack layout for uint256 (from highest bits to lowest)\n    /// (32 .. 16]      loc     16 bytes    Memory address of underlying bytes\n    /// (16 .. 00]      len     16 bytes    Length of underlying bytes\n\n    // ═══════════════════════════════════════════ BUILDING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Instantiate a new untyped memory view. This should generally not be called directly.\n     * Prefer `ref` wherever possible.\n     * @param loc_          The memory address\n     * @param len_          The length\n     * @return The new view with the specified location and length\n     */\n    function build(uint256 loc_, uint256 len_) internal pure returns (MemView) {\n        uint256 end_ = loc_ + len_;\n        // Make sure that a view is not constructed that points to unallocated memory\n        // as this could be indicative of a buffer overflow attack\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            if gt(end_, mload(0x40)) { end_ := 0 }\n        }\n        if (end_ == 0) {\n            revert UnallocatedMemory();\n        }\n        return _unsafeBuildUnchecked(loc_, len_);\n    }\n\n    /**\n     * @notice Instantiate a memory view from a byte array.\n     * @dev Note that due to Solidity memory representation, it is not possible to\n     * implement a deref, as the `bytes` type stores its len in memory.\n     * @param arr           The byte array\n     * @return The memory view over the provided byte array\n     */\n    function ref(bytes memory arr) internal pure returns (MemView) {\n        uint256 len_ = arr.length;\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 loc_;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // We add 0x20, so that the view starts exactly where the array data starts\n            loc_ := add(arr, 0x20)\n        }\n        return build(loc_, len_);\n    }\n\n    // ════════════════════════════════════════════ CLONING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to the new memory.\n     * @param memView       The memory view\n     * @return arr          The cloned byte array\n     */\n    function clone(MemView memView) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        unchecked {\n            _unsafeCopyTo(memView, ptr + 0x20);\n        }\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 len_ = memView.len();\n        uint256 footprint_ = memView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    /**\n     * @notice Copies all views, joins them into a new bytearray.\n     * @param memViews      The memory views\n     * @return arr          The new byte array with joined data behind the given views\n     */\n    function join(MemView[] memory memViews) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        MemView newView;\n        unchecked {\n            newView = _unsafeJoin(memViews, ptr + 0x20);\n        }\n        uint256 len_ = newView.len();\n        uint256 footprint_ = newView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    // ══════════════════════════════════════════ INSPECTING MEMORY VIEW ═══════════════════════════════════════════════\n\n    /**\n     * @notice Returns the memory address of the underlying bytes.\n     * @param memView       The memory view\n     * @return loc_         The memory address\n     */\n    function loc(MemView memView) internal pure returns (uint256 loc_) {\n        // loc is stored in the highest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u003e\u003e 128;\n    }\n\n    /**\n     * @notice Returns the number of bytes of the view.\n     * @param memView       The memory view\n     * @return len_         The length of the view\n     */\n    function len(MemView memView) internal pure returns (uint256 len_) {\n        // len is stored in the lowest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u0026 type(uint128).max;\n    }\n\n    /**\n     * @notice Returns the endpoint of `memView`.\n     * @param memView       The memory view\n     * @return end_         The endpoint of `memView`\n     */\n    function end(MemView memView) internal pure returns (uint256 end_) {\n        // The endpoint never overflows uint128, let alone uint256, so we could use unchecked math here\n        unchecked {\n            return memView.loc() + memView.len();\n        }\n    }\n\n    /**\n     * @notice Returns the number of memory words this memory view occupies, rounded up.\n     * @param memView       The memory view\n     * @return words_       The number of memory words\n     */\n    function words(MemView memView) internal pure returns (uint256 words_) {\n        // returning ceil(length / 32.0)\n        unchecked {\n            return (memView.len() + 31) \u003e\u003e 5;\n        }\n    }\n\n    /**\n     * @notice Returns the in-memory footprint of a fresh copy of the view.\n     * @param memView       The memory view\n     * @return footprint_   The in-memory footprint of a fresh copy of the view.\n     */\n    function footprint(MemView memView) internal pure returns (uint256 footprint_) {\n        // words() * 32\n        return memView.words() \u003c\u003c 5;\n    }\n\n    // ════════════════════════════════════════════ HASHING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the keccak256 hash of the underlying memory\n     * @param memView       The memory view\n     * @return digest       The keccak256 hash of the underlying memory\n     */\n    function keccak(MemView memView) internal pure returns (bytes32 digest) {\n        uint256 loc_ = memView.loc();\n        uint256 len_ = memView.len();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            digest := keccak256(loc_, len_)\n        }\n    }\n\n    /**\n     * @notice Adds a salt to the keccak256 hash of the underlying data and returns the keccak256 hash of the\n     * resulting data.\n     * @param memView       The memory view\n     * @return digestSalted keccak256(salt, keccak256(memView))\n     */\n    function keccakSalted(MemView memView, bytes32 salt) internal pure returns (bytes32 digestSalted) {\n        return keccak256(bytes.concat(salt, memView.keccak()));\n    }\n\n    // ════════════════════════════════════════════ SLICING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Safe slicing without memory modification.\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the given index\n     */\n    function slice(MemView memView, uint256 index_, uint256 len_) internal pure returns (MemView) {\n        uint256 loc_ = memView.loc();\n        // Ensure it doesn't overrun the view\n        if (loc_ + index_ + len_ \u003e memView.end()) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // loc_ + index_ \u003c= memView.end()\n            return build({loc_: loc_ + index_, len_: len_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing bytes from `index` to end(memView).\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @return The new view for the slice starting from the given index until the initial view endpoint\n     */\n    function sliceFrom(MemView memView, uint256 index_) internal pure returns (MemView) {\n        uint256 len_ = memView.len();\n        // Ensure it doesn't overrun the view\n        if (index_ \u003e len_) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // index_ \u003c= len_ =\u003e memView.loc() + index_ \u003c= memView.loc() + memView.len() == memView.end()\n            return build({loc_: memView.loc() + index_, len_: len_ - index_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the first `len` bytes.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the initial view beginning\n     */\n    function prefix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        return memView.slice({index_: 0, len_: len_});\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the last `len` byte.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length until the initial view endpoint\n     */\n    function postfix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        uint256 viewLen = memView.len();\n        // Ensure it doesn't overrun the view\n        if (len_ \u003e viewLen) {\n            revert ViewOverrun();\n        }\n        // Could do the unchecked math due to the check above\n        uint256 index_;\n        unchecked {\n            index_ = viewLen - len_;\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // len_ \u003c= memView.len() =\u003e memView.loc() \u003c= loc_ \u003c= memView.end()\n            return build({loc_: memView.loc() + viewLen - len_, len_: len_});\n        }\n    }\n\n    // ═══════════════════════════════════════════ INDEXING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Load up to 32 bytes from the view onto the stack.\n     * @dev Returns a bytes32 with only the `bytes_` HIGHEST bytes set.\n     * This can be immediately cast to a smaller fixed-length byte array.\n     * To automatically cast to an integer, use `indexUint`.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return result       The 32 byte result having only `bytes_` highest bytes set\n     */\n    function index(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (bytes32 result) {\n        if (bytes_ == 0) {\n            return bytes32(0);\n        }\n        // Can't load more than 32 bytes to the stack in one go\n        if (bytes_ \u003e 32) {\n            revert IndexedTooMuch();\n        }\n        // The last indexed byte should be within view boundaries\n        if (index_ + bytes_ \u003e memView.len()) {\n            revert ViewOverrun();\n        }\n        uint256 bitLength = bytes_ \u003c\u003c 3; // bytes_ * 8\n        uint256 loc_ = memView.loc();\n        // Get a mask with `bitLength` highest bits set\n        uint256 mask;\n        // 0x800...00 binary representation is 100...00\n        // sar stands for \"signed arithmetic shift\": https://en.wikipedia.org/wiki/Arithmetic_shift\n        // sar(N-1, 100...00) = 11...100..00, with exactly N highest bits set to 1\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            mask := sar(sub(bitLength, 1), 0x8000000000000000000000000000000000000000000000000000000000000000)\n        }\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load a full word using index offset, and apply mask to ignore non-relevant bytes\n            result := and(mload(add(loc_, index_)), mask)\n        }\n    }\n\n    /**\n     * @notice Parse an unsigned integer from the view at `index`.\n     * @dev Requires that the view have \u003e= `bytes_` bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return The unsigned integer\n     */\n    function indexUint(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (uint256) {\n        bytes32 indexedBytes = memView.index(index_, bytes_);\n        // `index()` returns left-aligned `bytes_`, while integers are right-aligned\n        // Shifting here to right-align with the full 32 bytes word: need to shift right `(32 - bytes_)` bytes\n        unchecked {\n            // memView.index() reverts when bytes_ \u003e 32, thus unchecked math\n            return uint256(indexedBytes) \u003e\u003e ((32 - bytes_) \u003c\u003c 3);\n        }\n    }\n\n    /**\n     * @notice Parse an address from the view at `index`.\n     * @dev Requires that the view have \u003e= 20 bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @return The address\n     */\n    function indexAddress(MemView memView, uint256 index_) internal pure returns (address) {\n        // index 20 bytes as `uint160`, and then cast to `address`\n        return address(uint160(memView.indexUint(index_, 20)));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns a memory view over the specified memory location\n    /// without checking if it points to unallocated memory.\n    function _unsafeBuildUnchecked(uint256 loc_, uint256 len_) private pure returns (MemView) {\n        // There is no scenario where loc or len would overflow uint128, so we omit this check.\n        // We use the highest 128 bits to encode the location and the lowest 128 bits to encode the length.\n        return MemView.wrap((loc_ \u003c\u003c 128) | len_);\n    }\n\n    /**\n     * @notice Copy the view to a location, return an unsafe memory reference\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memView       The memory view\n     * @param newLoc        The new location to copy the underlying view data\n     * @return The memory view over the unsafe memory with the copied underlying data\n     */\n    function _unsafeCopyTo(MemView memView, uint256 newLoc) private view returns (MemView) {\n        uint256 len_ = memView.len();\n        uint256 oldLoc = memView.loc();\n\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (newLoc \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        bool res;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // use the identity precompile (0x04) to copy\n            res := staticcall(gas(), 0x04, oldLoc, len_, newLoc, len_)\n        }\n        if (!res) revert PrecompileOutOfGas();\n        return _unsafeBuildUnchecked({loc_: newLoc, len_: len_});\n    }\n\n    /**\n     * @notice Join the views in memory, return an unsafe reference to the memory.\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memViews      The memory views\n     * @return The conjoined view pointing to the new memory\n     */\n    function _unsafeJoin(MemView[] memory memViews, uint256 location) private view returns (MemView) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (location \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        // Copy the views to the specified location one by one, by tracking the amount of copied bytes so far\n        uint256 offset = 0;\n        for (uint256 i = 0; i \u003c memViews.length;) {\n            MemView memView = memViews[i];\n            // We can use the unchecked math here as location + sum(view.length) will never overflow uint256\n            unchecked {\n                _unsafeCopyTo(memView, location + offset);\n                offset += memView.len();\n                ++i;\n            }\n        }\n        return _unsafeBuildUnchecked({loc_: location, len_: offset});\n    }\n}\n\n// contracts/libs/merkle/MerkleMath.sol\n\nlibrary MerkleMath {\n    // ═════════════════════════════════════════ BASIC MERKLE CALCULATIONS ═════════════════════════════════════════════\n\n    /**\n     * @notice Calculates the merkle root for the given leaf and merkle proof.\n     * @dev Will revert if proof length exceeds the tree height.\n     * @param index     Index of `leaf` in tree\n     * @param leaf      Leaf of the merkle tree\n     * @param proof     Proof of inclusion of `leaf` in the tree\n     * @param height    Height of the merkle tree\n     * @return root_    Calculated Merkle Root\n     */\n    function proofRoot(uint256 index, bytes32 leaf, bytes32[] memory proof, uint256 height)\n        internal\n        pure\n        returns (bytes32 root_)\n    {\n        // Proof length could not exceed the tree height\n        uint256 proofLen = proof.length;\n        if (proofLen \u003e height) revert TreeHeightTooLow();\n        root_ = leaf;\n        /// @dev Apply unchecked to all ++h operations\n        unchecked {\n            // Go up the tree levels from the leaf following the proof\n            for (uint256 h = 0; h \u003c proofLen; ++h) {\n                // Get a sibling node on current level: this is proof[h]\n                root_ = getParent(root_, proof[h], index, h);\n            }\n            // Go up to the root: the remaining siblings are EMPTY\n            for (uint256 h = proofLen; h \u003c height; ++h) {\n                root_ = getParent(root_, bytes32(0), index, h);\n            }\n        }\n    }\n\n    /**\n     * @notice Calculates the parent of a node on the path from one of the leafs to root.\n     * @param node          Node on a path from tree leaf to root\n     * @param sibling       Sibling for a given node\n     * @param leafIndex     Index of the tree leaf\n     * @param nodeHeight    \"Level height\" for `node` (ZERO for leafs, ORIGIN_TREE_HEIGHT for root)\n     */\n    function getParent(bytes32 node, bytes32 sibling, uint256 leafIndex, uint256 nodeHeight)\n        internal\n        pure\n        returns (bytes32 parent)\n    {\n        // Index for `node` on its \"tree level\" is (leafIndex / 2**height)\n        // \"Left child\" has even index, \"right child\" has odd index\n        if ((leafIndex \u003e\u003e nodeHeight) \u0026 1 == 0) {\n            // Left child\n            return getParent(node, sibling);\n        } else {\n            // Right child\n            return getParent(sibling, node);\n        }\n    }\n\n    /// @notice Calculates the parent of tow nodes in the merkle tree.\n    /// @dev We use implementation with H(0,0) = 0\n    /// This makes EVERY empty node in the tree equal to ZERO,\n    /// saving us from storing H(0,0), H(H(0,0), H(0, 0)), and so on\n    /// @param leftChild    Left child of the calculated node\n    /// @param rightChild   Right child of the calculated node\n    /// @return parent      Value for the node having above mentioned children\n    function getParent(bytes32 leftChild, bytes32 rightChild) internal pure returns (bytes32 parent) {\n        if (leftChild == bytes32(0) \u0026\u0026 rightChild == bytes32(0)) {\n            return 0;\n        } else {\n            return keccak256(bytes.concat(leftChild, rightChild));\n        }\n    }\n\n    // ════════════════════════════════ ROOT/PROOF CALCULATION FOR A LIST OF LEAFS ═════════════════════════════════════\n\n    /**\n     * @notice Calculates merkle root for a list of given leafs.\n     * Merkle Tree is constructed by padding the list with ZERO values for leafs until list length is `2**height`.\n     * Merkle Root is calculated for the constructed tree, and then saved in `leafs[0]`.\n     * \u003e Note:\n     * \u003e - `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * \u003e - Caller is expected not to reuse `hashes` list after the call, and only use `leafs[0]` value,\n     * which is guaranteed to contain the calculated merkle root.\n     * \u003e - root is calculated using the `H(0,0) = 0` Merkle Tree implementation. See MerkleTree.sol for details.\n     * @dev Amount of leaves should be at most `2**height`\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param height    Height of the Merkle Tree to construct\n     */\n    function calculateRoot(bytes32[] memory hashes, uint256 height) internal pure {\n        uint256 levelLength = hashes.length;\n        // Amount of hashes could not exceed amount of leafs in tree with the given height\n        if (levelLength \u003e (1 \u003c\u003c height)) revert TreeHeightTooLow();\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\": the amount of iterations for the for loop above.\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n            }\n        }\n    }\n\n    /**\n     * @notice Generates a proof of inclusion of a leaf in the list. If the requested index is outside\n     * of the list range, generates a proof of inclusion for an empty leaf (proof of non-inclusion).\n     * The Merkle Tree is constructed by padding the list with ZERO values until list length is a power of two\n     * __AND__ index is in the extended list range. For example:\n     *  - `hashes.length == 6` and `0 \u003c= index \u003c= 7` will \"extend\" the list to 8 entries.\n     *  - `hashes.length == 6` and `7 \u003c index \u003c= 15` will \"extend\" the list to 16 entries.\n     * \u003e Note: `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * Caller is expected not to reuse `hashes` list after the call.\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param index     Leaf index to generate the proof for\n     * @return proof    Generated merkle proof\n     */\n    function calculateProof(bytes32[] memory hashes, uint256 index) internal pure returns (bytes32[] memory proof) {\n        // Use only meaningful values for the shortened proof\n        // Check if index is within the list range (we want to generates proofs for outside leafs as well)\n        uint256 height = getHeight(index \u003c hashes.length ? hashes.length : (index + 1));\n        proof = new bytes32[](height);\n        uint256 levelLength = hashes.length;\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Use sibling for the merkle proof; `index^1` is index of our sibling\n                proof[h] = (index ^ 1 \u003c levelLength) ? hashes[index ^ 1] : bytes32(0);\n\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\"\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n                // Traverse to parent node\n                index \u003e\u003e= 1;\n            }\n        }\n    }\n\n    /// @notice Returns the height of the tree having a given amount of leafs.\n    function getHeight(uint256 leafs) internal pure returns (uint256 height) {\n        uint256 amount = 1;\n        while (amount \u003c leafs) {\n            unchecked {\n                ++height;\n            }\n            amount \u003c\u003c= 1;\n        }\n    }\n}\n\n// contracts/libs/stack/GasData.sol\n\n/// GasData in encoded data with \"basic information about gas prices\" for some chain.\ntype GasData is uint96;\n\nusing GasDataLib for GasData global;\n\n/// ChainGas is encoded data with given chain's \"basic information about gas prices\".\ntype ChainGas is uint128;\n\nusing GasDataLib for ChainGas global;\n\n/// Library for encoding and decoding GasData and ChainGas structs.\n/// # GasData\n/// `GasData` is a struct to store the \"basic information about gas prices\", that could\n/// be later used to approximate the cost of a message execution, and thus derive the\n/// minimal tip values for sending a message to the chain.\n/// \u003e - `GasData` is supposed to be cached by `GasOracle` contract, allowing to store the\n/// \u003e approximates instead of the exact values, and thus save on storage costs.\n/// \u003e - For instance, if `GasOracle` only updates the values on +- 10% change, having an\n/// \u003e 0.4% error on the approximates would be acceptable.\n/// `GasData` is supposed to be included in the Origin's state, which are synced across\n/// chains using Agent-signed snapshots and attestations.\n/// ## GasData stack layout (from highest bits to lowest)\n///\n/// | Position   | Field        | Type   | Bytes | Description                                         |\n/// | ---------- | ------------ | ------ | ----- | --------------------------------------------------- |\n/// | (012..010] | gasPrice     | uint16 | 2     | Gas price for the chain (in Wei per gas unit)       |\n/// | (010..008] | dataPrice    | uint16 | 2     | Calldata price (in Wei per byte of content)         |\n/// | (008..006] | execBuffer   | uint16 | 2     | Tx fee safety buffer for message execution (in Wei) |\n/// | (006..004] | amortAttCost | uint16 | 2     | Amortized cost for attestation submission (in Wei)  |\n/// | (004..002] | etherPrice   | uint16 | 2     | Chain's Ether Price / Mainnet Ether Price (in BWAD) |\n/// | (002..000] | markup       | uint16 | 2     | Markup for the message execution (in BWAD)          |\n/// \u003e See Number.sol for more details on `Number` type and BWAD (binary WAD) math.\n///\n/// ## ChainGas stack layout (from highest bits to lowest)\n///\n/// | Position   | Field   | Type   | Bytes | Description      |\n/// | ---------- | ------- | ------ | ----- | ---------------- |\n/// | (016..004] | gasData | uint96 | 12    | Chain's gas data |\n/// | (004..000] | domain  | uint32 | 4     | Chain's domain   |\nlibrary GasDataLib {\n    /// @dev Amount of bits to shift to gasPrice field\n    uint96 private constant SHIFT_GAS_PRICE = 10 * 8;\n    /// @dev Amount of bits to shift to dataPrice field\n    uint96 private constant SHIFT_DATA_PRICE = 8 * 8;\n    /// @dev Amount of bits to shift to execBuffer field\n    uint96 private constant SHIFT_EXEC_BUFFER = 6 * 8;\n    /// @dev Amount of bits to shift to amortAttCost field\n    uint96 private constant SHIFT_AMORT_ATT_COST = 4 * 8;\n    /// @dev Amount of bits to shift to etherPrice field\n    uint96 private constant SHIFT_ETHER_PRICE = 2 * 8;\n\n    /// @dev Amount of bits to shift to gasData field\n    uint128 private constant SHIFT_GAS_DATA = 4 * 8;\n\n    // ═════════════════════════════════════════════════ GAS DATA ══════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded GasData struct with the given fields.\n    /// @param gasPrice_        Gas price for the chain (in Wei per gas unit)\n    /// @param dataPrice_       Calldata price (in Wei per byte of content)\n    /// @param execBuffer_      Tx fee safety buffer for message execution (in Wei)\n    /// @param amortAttCost_    Amortized cost for attestation submission (in Wei)\n    /// @param etherPrice_      Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n    /// @param markup_          Markup for the message execution (in BWAD)\n    function encodeGasData(\n        Number gasPrice_,\n        Number dataPrice_,\n        Number execBuffer_,\n        Number amortAttCost_,\n        Number etherPrice_,\n        Number markup_\n    ) internal pure returns (GasData) {\n        // Number type wraps uint16, so could safely be casted to uint96\n        // forgefmt: disable-next-item\n        return GasData.wrap(\n            uint96(Number.unwrap(gasPrice_)) \u003c\u003c SHIFT_GAS_PRICE |\n            uint96(Number.unwrap(dataPrice_)) \u003c\u003c SHIFT_DATA_PRICE |\n            uint96(Number.unwrap(execBuffer_)) \u003c\u003c SHIFT_EXEC_BUFFER |\n            uint96(Number.unwrap(amortAttCost_)) \u003c\u003c SHIFT_AMORT_ATT_COST |\n            uint96(Number.unwrap(etherPrice_)) \u003c\u003c SHIFT_ETHER_PRICE |\n            uint96(Number.unwrap(markup_))\n        );\n    }\n\n    /// @notice Wraps padded uint256 value into GasData struct.\n    function wrapGasData(uint256 paddedGasData) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(paddedGasData));\n    }\n\n    /// @notice Returns the gas price, in Wei per gas unit.\n    function gasPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_GAS_PRICE));\n    }\n\n    /// @notice Returns the calldata price, in Wei per byte of content.\n    function dataPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_DATA_PRICE));\n    }\n\n    /// @notice Returns the tx fee safety buffer for message execution, in Wei.\n    function execBuffer(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_EXEC_BUFFER));\n    }\n\n    /// @notice Returns the amortized cost for attestation submission, in Wei.\n    function amortAttCost(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_AMORT_ATT_COST));\n    }\n\n    /// @notice Returns the ratio of Chain's Ether Price / Mainnet Ether Price, in BWAD math.\n    function etherPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_ETHER_PRICE));\n    }\n\n    /// @notice Returns the markup for the message execution, in BWAD math.\n    function markup(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data)));\n    }\n\n    // ════════════════════════════════════════════════ CHAIN DATA ═════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded ChainGas struct with the given fields.\n    /// @param gasData_ Chain's gas data\n    /// @param domain_  Chain's domain\n    function encodeChainGas(GasData gasData_, uint32 domain_) internal pure returns (ChainGas) {\n        // GasData type wraps uint96, so could safely be casted to uint128\n        return ChainGas.wrap(uint128(GasData.unwrap(gasData_)) \u003c\u003c SHIFT_GAS_DATA | uint128(domain_));\n    }\n\n    /// @notice Wraps padded uint256 value into ChainGas struct.\n    function wrapChainGas(uint256 paddedChainGas) internal pure returns (ChainGas) {\n        // Casting to uint128 will truncate the highest bits, which is the behavior we want\n        return ChainGas.wrap(uint128(paddedChainGas));\n    }\n\n    /// @notice Returns the chain's gas data.\n    function gasData(ChainGas data) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(ChainGas.unwrap(data) \u003e\u003e SHIFT_GAS_DATA));\n    }\n\n    /// @notice Returns the chain's domain.\n    function domain(ChainGas data) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(ChainGas.unwrap(data));\n    }\n\n    /// @notice Returns the hash for the list of ChainGas structs.\n    function snapGasHash(ChainGas[] memory snapGas) internal pure returns (bytes32 snapGasHash_) {\n        // Use assembly to calculate the hash of the array without copying it\n        // ChainGas takes a single word of storage, thus ChainGas[] is stored in the following way:\n        // 0x00: length of the array, in words\n        // 0x20: first ChainGas struct\n        // 0x40: second ChainGas struct\n        // And so on...\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Find the location where the array data starts, we add 0x20 to skip the length field\n            let loc := add(snapGas, 0x20)\n            // Load the length of the array (in words).\n            // Shifting left 5 bits is equivalent to multiplying by 32: this converts from words to bytes.\n            let len := shl(5, mload(snapGas))\n            // Calculate the hash of the array\n            snapGasHash_ := keccak256(loc, len)\n        }\n    }\n}\n\n// contracts/libs/stack/Header.sol\n\n/// Header is encoded data with \"general routing information\".\ntype Header is uint136;\n\nusing HeaderLib for Header global;\n\n/// Types of messages supported by Origin-Destination\n/// - Base: message sent by protocol user, contains tips\n/// - Manager: message sent between AgentManager contracts located on different chains, no tips\nenum MessageFlag {\n    Base,\n    Manager\n}\n\nusing HeaderLib for MessageFlag global;\n\n/// Library for formatting _the header part_ of _the messages used by Origin and Destination_.\n/// - Header represents general information for routing a Message for Origin and Destination.\n/// - Header occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n///\n/// # Header stack layout (from highest bits to lowest)\n///\n/// | Position   | Field            | Type   | Bytes | Description                             |\n/// | ---------- | ---------------- | ------ | ----- | --------------------------------------- |\n/// | (017..016] | flag             | uint8  | 1     | Flag specifying the type of message     |\n/// | (016..012] | origin           | uint32 | 4     | Domain where message originated         |\n/// | (012..008] | nonce            | uint32 | 4     | Message nonce on the origin domain      |\n/// | (008..004] | destination      | uint32 | 4     | Domain where message will be executed   |\n/// | (004..000] | optimisticPeriod | uint32 | 4     | Optimistic period that will be enforced |\nlibrary HeaderLib {\n    /// @dev Amount of bits to shift to flag field\n    uint136 private constant SHIFT_FLAG = 16 * 8;\n    /// @dev Amount of bits to shift to origin field\n    uint136 private constant SHIFT_ORIGIN = 12 * 8;\n    /// @dev Amount of bits to shift to nonce field\n    uint136 private constant SHIFT_NONCE = 8 * 8;\n    /// @dev Amount of bits to shift to destination field\n    uint136 private constant SHIFT_DESTINATION = 4 * 8;\n\n    /// @notice Returns an encoded header with provided fields\n    /// @param origin_              Domain of origin chain\n    /// @param nonce_               Message nonce on origin chain\n    /// @param destination_         Domain of destination chain\n    /// @param optimisticPeriod_    Optimistic period for message execution\n    function encodeHeader(\n        MessageFlag flag_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint32 destination_,\n        uint32 optimisticPeriod_\n    ) internal pure returns (Header) {\n        // All casts below are upcasts, so they are safe\n        // forgefmt: disable-next-item\n        return Header.wrap(\n            uint136(uint8(flag_)) \u003c\u003c SHIFT_FLAG |\n            uint136(origin_) \u003c\u003c SHIFT_ORIGIN |\n            uint136(nonce_) \u003c\u003c SHIFT_NONCE |\n            uint136(destination_) \u003c\u003c SHIFT_DESTINATION |\n            uint136(optimisticPeriod_)\n        );\n    }\n\n    /// @notice Checks that the header is a valid encoded header.\n    function isHeader(uint256 paddedHeader) internal pure returns (bool) {\n        // Check that flag is within range\n        return _flag(paddedHeader) \u003c= uint8(type(MessageFlag).max);\n    }\n\n    /// @notice Wraps the padded encoded request into a Header-typed value.\n    /// @dev The \"padded\" header is simply an encoded header casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded headers\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedHeader) internal pure returns (Header) {\n        // Check that flag is within range\n        if (!isHeader(paddedHeader)) revert FlagOutOfRange();\n        // Casting to uint136 will truncate the highest bits, which is the behavior we want\n        return Header.wrap(uint136(paddedHeader));\n    }\n\n    /// @notice Returns header's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Header header) internal pure returns (bytes32 hashedHeader) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store header in scratch space\n            mstore(0, header)\n            // Compute hash of header padded to 32 bytes\n            hashedHeader := keccak256(0, 32)\n        }\n    }\n\n    // ══════════════════════════════════════════════ HEADER SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns header's flag field\n    function flag(Header header) internal pure returns (MessageFlag) {\n        // We check that flag is within range when wrapping the header, so this cast is safe\n        return MessageFlag(_flag(Header.unwrap(header)));\n    }\n\n    /// @notice Returns header's origin field\n    function origin(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_ORIGIN);\n    }\n\n    /// @notice Returns header's nonce field\n    function nonce(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_NONCE);\n    }\n\n    /// @notice Returns header's destination field\n    function destination(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_DESTINATION);\n    }\n\n    /// @notice Returns header's optimistic seconds field\n    function optimisticPeriod(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns header's flag field without casting to MessageFlag\n    function _flag(uint256 paddedHeader) private pure returns (uint8) {\n        // Casting to uint8 will truncate the highest bits, which is the behavior we want\n        return uint8(paddedHeader \u003e\u003e SHIFT_FLAG);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n     * constructor.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall \u0026\u0026 _initialized \u003c 1) || (!AddressUpgradeable.isContract(address(this)) \u0026\u0026 _initialized == 1),\n            \"Initializable: contract is already initialized\"\n        );\n        _initialized = 1;\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: setting the version to 255 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing \u0026\u0026 _initialized \u003c version, \"Initializable: contract is already initialized\");\n        _initialized = version;\n        _initializing = true;\n        _;\n        _initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        require(_initializing, \"Initializable: contract is not initializing\");\n        _;\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized != type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint8) {\n        return _initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _initializing;\n    }\n}\n\n// contracts/interfaces/IAgentManager.sol\n\ninterface IAgentManager {\n    /**\n     * @notice Allows Inbox to open a Dispute between a Guard and a Notary, if they are both not in Dispute already.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Guard or Notary is already in Dispute.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Allows Inbox to slash an agent, if their fraud was proven.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Domain doesn't match the saved agent domain.\n     * @param domain    Domain where the Agent is active\n     * @param agent     Address of the Agent\n     * @param prover    Address that initially provided fraud proof\n     */\n    function slashAgent(uint32 domain, address agent, address prover) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest known root of the Agent Merkle Tree.\n     */\n    function agentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns the number of opened Disputes.\n     * @dev This includes the Disputes that have been resolved already.\n     */\n    function getDisputesAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns information about the dispute with the given index.\n     * @dev Will revert if dispute with given index hasn't been opened yet.\n     * @param index             Dispute index\n     * @return guard            Address of the Guard in the Dispute\n     * @return notary           Address of the Notary in the Dispute\n     * @return slashedAgent     Address of the Agent who was slashed when Dispute was resolved\n     * @return fraudProver      Address who provided fraud proof to resolve the Dispute\n     * @return reportPayload    Raw payload with report data that led to the Dispute\n     * @return reportSignature  Guard signature for the report payload\n     */\n    function getDispute(uint256 index)\n        external\n        view\n        returns (\n            address guard,\n            address notary,\n            address slashedAgent,\n            address fraudProver,\n            bytes memory reportPayload,\n            bytes memory reportSignature\n        );\n\n    /**\n     * @notice Returns the current Dispute status of a given agent. See Structures.sol for details.\n     * @dev Every returned value will be set to zero if agent was not slashed and is not in Dispute.\n     * `rival` and `disputePtr` will be set to zero if the agent was slashed without being in Dispute.\n     * @param agent         Agent address\n     * @return flag         Flag describing the current Dispute status for the agent: None/Pending/Slashed\n     * @return rival        Address of the rival agent in the Dispute\n     * @return fraudProver  Address who provided fraud proof to resolve the Dispute\n     * @return disputePtr   Index of the opened Dispute PLUS ONE. Zero if agent is not in Dispute.\n     */\n    function disputeStatus(address agent)\n        external\n        view\n        returns (DisputeFlag flag, address rival, address fraudProver, uint256 disputePtr);\n}\n\n// contracts/interfaces/IAgentSecured.sol\n\ninterface IAgentSecured {\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * between a Guard and a Notary has been opened.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * has been resolved due to one of the agents being slashed.\n     * \u003e `rivalIndex` will be ZERO, if the slashed agent was not in the Dispute.\n     * @param slashedIndex  Index of the slashed agent in the Agent Merkle Tree\n     * @param rivalIndex    Index of the their Dispute Rival in the Agent Merkle Tree\n     */\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the address of the local AgentManager contract, which is treated as\n     * the \"source of truth\" for agent statuses.\n     */\n    function agentManager() external view returns (address);\n\n    /**\n     * @notice Returns the address of the local Inbox contract, which is treated as\n     * the \"source of truth\" for agent-signed statements.\n     * @dev Inbox passes verified agent statements to `IAgentSecured` contract.\n     */\n    function inbox() external view returns (address);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns (flag, openedAt, resolvedAt) that describes the latest status of\n     * the latest dispute for an agent with a given index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param agentIndex    Agent index in the Agent Merkle Tree\n     * @return              Latest dispute status for the given agent: (flag, openedAt, resolvedAt)\n     */\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory);\n}\n\n// contracts/libs/memory/ByteString.sol\n\n/// @dev CallData is a memory view over the payload to be used for an external call, i.e.\n/// recipient.call(callData). Its length is always (4 + 32 * N) bytes:\n/// - First 4 bytes represent the function selector.\n/// - 32 * N bytes represent N words that function arguments occupy.\ntype CallData is uint256;\n\n/// @dev Attach library functions to CallData\nusing ByteString for CallData global;\n\n/// @dev Signature is a memory view over a \"65 bytes\" array representing a ECDSA signature.\ntype Signature is uint256;\n\n/// @dev Attach library functions to Signature\nusing ByteString for Signature global;\n\nlibrary ByteString {\n    using MemViewLib for bytes;\n\n    /**\n     * @dev non-compact ECDSA signatures are enforced as of OZ 4.7.3\n     *\n     *      Signature payload memory layout\n     * [000 .. 032) r   bytes32 32 bytes\n     * [032 .. 064) s   bytes32 32 bytes\n     * [064 .. 065) v   uint8    1 byte\n     */\n    uint256 internal constant SIGNATURE_LENGTH = 65;\n    uint256 private constant OFFSET_R = 0;\n    uint256 private constant OFFSET_S = 32;\n    uint256 private constant OFFSET_V = 64;\n\n    /**\n     * @dev Calldata memory layout\n     * [000 .. 004) selector    bytes4  4 bytes\n     *      Optional: N function arguments\n     * [004 .. 036) arg1        bytes32 32 bytes\n     *      ..\n     * [AAA .. END) argN        bytes32 32 bytes\n     */\n    uint256 internal constant SELECTOR_LENGTH = 4;\n    uint256 private constant OFFSET_SELECTOR = 0;\n    uint256 private constant OFFSET_ARGUMENTS = SELECTOR_LENGTH;\n\n    // ═════════════════════════════════════════════════ SIGNATURE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the signature payload from the given values.\n     * @dev Using ByteString.formatSignature({r: r, s: s, v: v}) will make sure\n     * that params are given in the right order.\n     */\n    function formatSignature(bytes32 r, bytes32 s, uint8 v) internal pure returns (bytes memory) {\n        return abi.encodePacked(r, s, v);\n    }\n\n    /**\n     * @notice Returns a Signature view over for the given payload.\n     * @dev Will revert if the payload is not a signature.\n     */\n    function castToSignature(bytes memory payload) internal pure returns (Signature) {\n        return castToSignature(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Signature view.\n     * @dev Will revert if the memory view is not over a signature.\n     */\n    function castToSignature(MemView memView) internal pure returns (Signature) {\n        if (!isSignature(memView)) revert UnformattedSignature();\n        return Signature.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a signature\n     */\n    function isSignature(MemView memView) internal pure returns (bool) {\n        return memView.len() == SIGNATURE_LENGTH;\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Signature signature) internal pure returns (MemView) {\n        return MemView.wrap(Signature.unwrap(signature));\n    }\n\n    // ═════════════════════════════════════════════ SIGNATURE SLICING ═════════════════════════════════════════════════\n\n    /// @notice Unpacks signature payload into (r, s, v) parameters.\n    /// @dev Make sure to verify signature length with isSignature() beforehand.\n    function toRSV(Signature signature) internal pure returns (bytes32 r, bytes32 s, uint8 v) {\n        // Get the underlying memory view\n        MemView memView = unwrap(signature);\n        r = memView.index({index_: OFFSET_R, bytes_: 32});\n        s = memView.index({index_: OFFSET_S, bytes_: 32});\n        // Can be safely casted to uint8, since we index a single byte\n        v = uint8(memView.indexUint({index_: OFFSET_V, bytes_: 1}));\n    }\n\n    // ═════════════════════════════════════════════════ CALLDATA ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the calldata with the modified arguments:\n     * the existing arguments are prepended with the arguments from the prefix.\n     * @dev Given:\n     *  - `calldata = abi.encodeWithSelector(foo.selector, d, e);`\n     *  - `prefix = abi.encode(a, b, c);`\n     *  - `a`, `b`, `c` are arguments of static type (i.e. not dynamically sized ones)\n     *      Then:\n     *  - Function will return abi.encodeWithSelector(foo.selector, a, c, c, d, e)\n     *  - Returned calldata will trigger `foo(a, b, c, d, e)` when used for a contract call.\n     * Note: for clarification as to what types are considered static, see\n     * https://docs.soliditylang.org/en/latest/abi-spec.html#formal-specification-of-the-encoding\n     * @param callData  Calldata that needs to be modified\n     * @param prefix    ABI-encoded arguments to use as the first arguments in the new calldata\n     * @return Modified calldata having prefix as the first arguments.\n     */\n    function addPrefix(CallData callData, bytes memory prefix) internal view returns (bytes memory) {\n        // Prefix should occupy a whole amount of words in memory\n        if (!_fullWords(prefix.length)) revert UnformattedCallDataPrefix();\n        MemView[] memory views = new MemView[](3);\n        // Use payload's function selector\n        views[0] = abi.encodePacked(callData.callSelector()).ref();\n        // Use prefix as the first arguments\n        views[1] = prefix.ref();\n        // Use payload's remaining arguments\n        views[2] = callData.arguments();\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a CallData view over for the given payload.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(bytes memory payload) internal pure returns (CallData) {\n        return castToCallData(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a CallData view.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(MemView memView) internal pure returns (CallData) {\n        if (!isCallData(memView)) revert UnformattedCallData();\n        return CallData.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a valid calldata, i.e.\n     * a function selector, followed by arbitrary amount of arguments.\n     */\n    function isCallData(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Calldata should at least have a function selector\n        if (length \u003c SELECTOR_LENGTH) return false;\n        // The remainder of the calldata should be exactly N memory words (N \u003e= 0)\n        return _fullWords(length - SELECTOR_LENGTH);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(CallData callData) internal pure returns (MemView) {\n        return MemView.wrap(CallData.unwrap(callData));\n    }\n\n    /// @notice Returns callData's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(CallData callData) internal pure returns (bytes32) {\n        return callData.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ CALLDATA SLICING ══════════════════════════════════════════════════\n\n    /**\n     * @notice Returns amount of memory words (32 byte chunks) the function arguments\n     * occupy in the calldata.\n     * @dev This might differ from amount of arguments supplied, if any of the arguments\n     * occupies more than one memory slot. It is true, however, that argument part of the payload\n     * occupies exactly N words, even for dynamic types like `bytes`\n     */\n    function argumentWords(CallData callData) internal pure returns (uint256) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        // Equivalent of (length - SELECTOR_LENGTH) / 32\n        return (memView.len() - SELECTOR_LENGTH) \u003e\u003e 5;\n    }\n\n    /// @notice Returns selector for the provided calldata.\n    function callSelector(CallData callData) internal pure returns (bytes4) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return bytes4(memView.index({index_: OFFSET_SELECTOR, bytes_: SELECTOR_LENGTH}));\n    }\n\n    /// @notice Returns abi encoded arguments for the provided calldata.\n    function arguments(CallData callData) internal pure returns (MemView) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return memView.sliceFrom({index_: OFFSET_ARGUMENTS});\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if length is full amount of memory words (32 bytes).\n    function _fullWords(uint256 length) internal pure returns (bool) {\n        // The equivalent of length % 32 == 0\n        return length \u0026 31 == 0;\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n    function __Context_init() internal onlyInitializing {\n    }\n\n    function __Context_init_unchained() internal onlyInitializing {\n    }\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[50] private __gap;\n}\n\n// contracts/libs/merkle/MerkleTree.sol\n\n/// `BaseTree` is a struct representing incremental merkle tree.\n/// - Contains only the current branch.\n/// - The number of inserted leaves is stored externally, and is later supplied for tree operations.\n/// - Has a fixed height of `ORIGIN_TREE_HEIGHT`.\n/// - Can store up to `2 ** ORIGIN_TREE_HEIGHT - 1` leaves.\n/// \u003e Note: the hash function for the tree `H(x, y)` is defined as:\n/// \u003e - `H(0,0) = 0`\n/// \u003e - `H(x,y) = keccak256(x, y), when (x != 0 || y != 0)`\n/// ## Invariant for leafs\n/// - The leftmost empty leaf has `index == count`, where `count` is the amount of the inserted leafs so far.\n/// - Value for any empty leaf or node is bytes32(0).\n/// ## Invariant for current branch\n/// `branch[i]` is always the value of a node on the i-th level.\n/// Levels are numbered from leafs to root: `0 .. ORIGIN_TREE_HEIGHT`.\n/// `branch[i]` stores the value for the node, such that:\n//  - The node is a \"left child\" (e.g. has an even index).\n/// - The node must have two non-empty children.\n/// - Out of all level's \"left child\" nodes with \"non-empty children\",\n/// the one with the biggest index (the rightmost one) is stored as `branch[i]`.\n/// \u003e __`branch` could be used to form a proof of inclusion for the first empty leaf (`index == count`).__\n/// _Here is how:_\n/// - Let's walk along the path from the \"first empty leaf\" to the root.\n/// - i-th bit of the \"first empty leaf\" index (which is equal to `count`) determines if the path's node\n/// for this i-th level is a \"left child\" or a \"right child\".\n/// - i-th bit in `count` is 0 → we are the left child on this level → sibling is the right child\n/// that does not exist yet → `proof[i] = bytes32(0)`.\n/// - i-th bit in `count` is 1 → we are the right child on this level → sibling is the left child\n/// sibling is the rightmost \"left child\" node on the level → `proof[i] = branch[i]`.\n/// \u003e Therefore `proof[i] = (count \u0026 (1 \u003c\u003c i)) == 0 ? bytes32(0) : branch[i])`\nstruct BaseTree {\n    bytes32[ORIGIN_TREE_HEIGHT] branch;\n}\n\nusing MerkleTree for BaseTree global;\n\n/// `HistoricalTree` is an incremental merkle tree keeping track of its historical merkle roots.\n/// \u003e - `roots[N]` is the root of the tree after `N` leafs were inserted\n/// \u003e - `roots[0] == bytes32(0)`\n/// @param tree     Incremental merkle tree\n/// @param roots    Historical merkle roots of the tree\nstruct HistoricalTree {\n    BaseTree tree;\n    bytes32[] roots;\n}\n\nusing MerkleTree for HistoricalTree global;\n\n/// `DynamicTree` is a struct representing a Merkle Tree with `2**AGENT_TREE_HEIGHT` leaves.\n/// - A single operation is available: update value for leaf with an arbitrary index (which might be a non-empty leaf).\n/// - This is done by requesting the proof of inclusion for the old value, which is used to both\n/// verify the old value, and calculate the new root.\n/// \u003e Based on Original idea from [ER forum post](https://ethresear.ch/t/efficient-on-chain-dynamic-merkle-tree/11054).\nstruct DynamicTree {\n    bytes32 root;\n}\n\nusing MerkleTree for DynamicTree global;\n\n/// MerkleTree is work based on Nomad's Merkle.sol, which is used under MIT OR Apache-2.0\n/// [link](https://github.com/nomad-xyz/monorepo/blob/main/packages/contracts-core/contracts/libs/Merkle.sol).\n/// With the following changes:\n/// - Adapted for Solidity 0.8.x.\n/// - Amount of tree leaves stored externally.\n/// - Added thorough documentation.\n/// - `H(0,0) = 0` optimization from [ER forum post](https://ethresear.ch/t/optimizing-sparse-merkle-trees/3751/6).\n/// \u003e Nomad's Merkle.sol is work based on eth2 deposit contract, which is used under CC0-1.0\n///[link](https://github.com/ethereum/deposit_contract/blob/dev/deposit_contract/contracts/validator_registration.v.py).\n/// With the following changes:\n/// \u003e - Implemented in Solidity 0.7.6 (eth2 deposit contract implemented in Vyper).\n/// \u003e - `H() = keccak256()` is used as the hashing function instead of `sha256()`.\nlibrary MerkleTree {\n    /// @dev For root calculation we need at least one empty leaf, thus the minus one in the formula.\n    uint256 internal constant MAX_LEAVES = 2 ** ORIGIN_TREE_HEIGHT - 1;\n\n    // ═════════════════════════════════════════════════ BASE TREE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Inserts `node` into merkle tree\n     * @dev Reverts if tree is full\n     * @param newCount  Amount of inserted leaves in the tree after the insertion (i.e. current + 1)\n     * @param node      Element to insert into tree\n     */\n    function insertBase(BaseTree storage tree, uint256 newCount, bytes32 node) internal {\n        if (newCount \u003e MAX_LEAVES) revert MerkleTreeFull();\n        // We go up the tree following the branch from the empty leaf AFTER the just inserted one.\n        // We stop when we find the first \"right child\" node.\n        // Its sibling is now the rightmost \"left child\" node that has two non-empty children.\n        // Therefore we need to update `tree.branch` value on this level.\n        // One could see that `tree.branch` value on lower and higher levels remain unchanged.\n\n        // Loop invariant: `node` is the current level's value for the branch from JUST INSERTED leaf\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            if ((newCount \u0026 1) == 1) {\n                // Found the first \"right child\" node on the branch from EMPTY leaf\n                // `node` is the value for node on branch from JUST INSERTED leaf\n                // Which in this case is the \"left child\".\n                // We update tree.branch and exit\n                tree.branch[i] = node;\n                return;\n            }\n            // On the branch from EMPTY leaf this is still a \"left child\".\n            // Meaning on branch from JUST INSERTED leaf, `node` is a right child.\n            // We compute value for `node` parent using `tree.branch` invariant:\n            // This is the rightmost \"left child\" node, which would be sibling of `node`.\n            node = MerkleMath.getParent(tree.branch[i], node);\n            // Get the parent index, and go to the next tree level\n            newCount \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n        // As the loop should always end prematurely with the `return` statement,\n        // this code should be unreachable. We assert `false` just to be safe.\n        assert(false);\n    }\n\n    /**\n     * @notice Calculates and returns current root of the merkle tree.\n     * @param count     Current amount of inserted leaves in the tree\n     * @return current  Calculated root of `tree`\n     */\n    function rootBase(BaseTree storage tree, uint256 count) internal view returns (bytes32 current) {\n        // To calculate the root we follow the branch of first EMPTY leaf (index == count)\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            // Check if we are the left or the right child on the current level\n            if ((count \u0026 1) == 1) {\n                // We are the right child. Our sibling is the \"rightmost\" \"left-child\" node\n                // that has two non-empty children → sibling is `tree.branch[i]`\n                current = MerkleMath.getParent(tree.branch[i], current);\n            } else {\n                // We are the left child. Our sibling does not exist yet → sibling is EMPTY\n                current = MerkleMath.getParent(current, bytes32(0));\n            }\n            // Get the parent index, and go to the next tree level\n            count \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    // ══════════════════════════════════════════════ HISTORICAL TREE ══════════════════════════════════════════════════\n\n    /// @notice Initializes the historical roots for the tree by inserting an empty root.\n    // solhint-disable-next-line ordering\n    function initializeRoots(HistoricalTree storage tree) internal returns (bytes32 savedRoot) {\n        // This should only be called once, when the contract is initialized\n        assert(tree.roots.length == 0);\n        // Save root for empty merkle tree: bytes32(0)\n        tree.roots.push(savedRoot);\n    }\n\n    /// @notice Inserts a new leaf into the merkle tree.\n    /// @dev Reverts if tree is full.\n    /// @param node         Element to insert into tree\n    /// @return newRoot     Merkle root after the leaf was inserted\n    function insert(HistoricalTree storage tree, bytes32 node) internal returns (bytes32 newRoot) {\n        // Tree count after the new leaf will be inserted (we store roots[0] as root of empty tree)\n        uint256 newCount = tree.roots.length;\n        tree.tree.insertBase(newCount, node);\n        // Save the new root\n        newRoot = tree.tree.rootBase(newCount);\n        tree.roots.push(newRoot);\n    }\n\n    /// @notice Returns the historical root of the merkle tree.\n    /// @dev Reverts if not enough leafs have been inserted.\n    /// @param count            Amount of leafs in the tree at some point of time\n    /// @return historicalRoot  Merkle root after `count` leafs were inserted\n    function root(HistoricalTree storage tree, uint256 count) internal view returns (bytes32 historicalRoot) {\n        if (count \u003e= tree.roots.length) revert NotEnoughLeafs();\n        return tree.roots[count];\n    }\n\n    // ═══════════════════════════════════════════════ DYNAMIC TREE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Updates the value for the leaf with the given index in the Dynamic Merkle Tree.\n     * @dev Will revert if incorrect proof of inclusion for old value is supplied.\n     * @param tree          Dynamic merkle tree\n     * @param index         Index of the leaf to update\n     * @param oldValue      Previous value of the leaf\n     * @param branch        Proof of inclusion of previous value into the tree\n     * @param newValue      New leaf value to assign\n     * @return newRoot      New value for the Merkle Root after the leaf is updated\n     */\n    function update(\n        DynamicTree storage tree,\n        uint256 index,\n        bytes32 oldValue,\n        bytes32[] memory branch,\n        bytes32 newValue\n    ) internal returns (bytes32 newRoot) {\n        // Check that the old value + proof result in a correct root\n        if (MerkleMath.proofRoot(index, oldValue, branch, AGENT_TREE_HEIGHT) != tree.root) {\n            revert LeafNotProven();\n        }\n        // New root is new value + the same proof (values for sibling nodes are not updated)\n        newRoot = MerkleMath.proofRoot(index, newValue, branch, AGENT_TREE_HEIGHT);\n        // Write the new root\n        tree.root = newRoot;\n    }\n}\n\n// contracts/libs/stack/Tips.sol\n\n/// Tips is encoded data with \"tips paid for sending a base message\".\n/// Note: even though uint256 is also an underlying type for MemView, Tips is stored ON STACK.\ntype Tips is uint256;\n\nusing TipsLib for Tips global;\n\n/// # Tips\n/// Library for formatting _the tips part_ of _the base messages_.\n///\n/// ## How the tips are awarded\n/// Tips are paid for sending a base message, and are split across all the agents that\n/// made the message execution on destination chain possible.\n/// ### Summit tips\n/// Split between:\n///     - Guard posting a snapshot with state ST_G for the origin chain.\n///     - Notary posting a snapshot SN_N using ST_G. This creates attestation A.\n///     - Notary posting a message receipt after it is executed on destination chain.\n/// ### Attestation tips\n/// Paid to:\n///     - Notary posting attestation A to destination chain.\n/// ### Execution tips\n/// Paid to:\n///     - First executor performing a valid execution attempt (correct proofs, optimistic period over),\n///      using attestation A to prove message inclusion on origin chain, whether the recipient reverted or not.\n/// ### Delivery tips.\n/// Paid to:\n///     - Executor who successfully executed the message on destination chain.\n///\n/// ## Tips encoding\n/// - Tips occupy a single storage word, and thus are stored on stack instead of being stored in memory.\n/// - The actual tip values should be determined by multiplying stored values by divided by TIPS_MULTIPLIER=2**32.\n/// - Tips are packed into a single word of storage, while allowing real values up to ~8*10**28 for every tip category.\n/// \u003e The only downside is that the \"real tip values\" are now multiplies of ~4*10**9, which should be fine even for\n/// the chains with the most expensive gas currency.\n/// # Tips stack layout (from highest bits to lowest)\n///\n/// | Position   | Field          | Type   | Bytes | Description                                                |\n/// | ---------- | -------------- | ------ | ----- | ---------------------------------------------------------- |\n/// | (032..024] | summitTip      | uint64 | 8     | Tip for agents interacting with Summit contract            |\n/// | (024..016] | attestationTip | uint64 | 8     | Tip for Notary posting attestation to Destination contract |\n/// | (016..008] | executionTip   | uint64 | 8     | Tip for valid execution attempt on destination chain       |\n/// | (008..000] | deliveryTip    | uint64 | 8     | Tip for successful message delivery on destination chain   |\n\nlibrary TipsLib {\n    using SafeCast for uint256;\n\n    /// @dev Amount of bits to shift to summitTip field\n    uint256 private constant SHIFT_SUMMIT_TIP = 24 * 8;\n    /// @dev Amount of bits to shift to attestationTip field\n    uint256 private constant SHIFT_ATTESTATION_TIP = 16 * 8;\n    /// @dev Amount of bits to shift to executionTip field\n    uint256 private constant SHIFT_EXECUTION_TIP = 8 * 8;\n\n    // ═══════════════════════════════════════════════════ TIPS ════════════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips with the given fields\n    /// @param summitTip_        Tip for agents interacting with Summit contract, divided by TIPS_MULTIPLIER\n    /// @param attestationTip_   Tip for Notary posting attestation to Destination contract, divided by TIPS_MULTIPLIER\n    /// @param executionTip_     Tip for valid execution attempt on destination chain, divided by TIPS_MULTIPLIER\n    /// @param deliveryTip_      Tip for successful message delivery on destination chain, divided by TIPS_MULTIPLIER\n    function encodeTips(uint64 summitTip_, uint64 attestationTip_, uint64 executionTip_, uint64 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // forgefmt: disable-next-item\n        return Tips.wrap(\n            uint256(summitTip_) \u003c\u003c SHIFT_SUMMIT_TIP |\n            uint256(attestationTip_) \u003c\u003c SHIFT_ATTESTATION_TIP |\n            uint256(executionTip_) \u003c\u003c SHIFT_EXECUTION_TIP |\n            uint256(deliveryTip_)\n        );\n    }\n\n    /// @notice Convenience function to encode tips with uint256 values.\n    function encodeTips256(uint256 summitTip_, uint256 attestationTip_, uint256 executionTip_, uint256 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // In practice, the tips amounts are not supposed to be higher than 2**96, and with 32 bits of granularity\n        // using uint64 is enough to store the values. However, we still check for overflow just in case.\n        // TODO: consider using Number type to store the tips values.\n        return encodeTips({\n            summitTip_: (summitTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            attestationTip_: (attestationTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            executionTip_: (executionTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            deliveryTip_: (deliveryTip_ \u003e\u003e TIPS_GRANULARITY).toUint64()\n        });\n    }\n\n    /// @notice Wraps the padded encoded tips into a Tips-typed value.\n    /// @dev There is no actual padding here, as the underlying type is already uint256,\n    /// but we include this function for consistency and to be future-proof, if tips will eventually use anything\n    /// smaller than uint256.\n    function wrapPadded(uint256 paddedTips) internal pure returns (Tips) {\n        return Tips.wrap(paddedTips);\n    }\n\n    /**\n     * @notice Returns a formatted Tips payload specifying empty tips.\n     * @return Formatted tips\n     */\n    function emptyTips() internal pure returns (Tips) {\n        return Tips.wrap(0);\n    }\n\n    /// @notice Returns tips's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Tips tips) internal pure returns (bytes32 hashedTips) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store tips in scratch space\n            mstore(0, tips)\n            // Compute hash of tips padded to 32 bytes\n            hashedTips := keccak256(0, 32)\n        }\n    }\n\n    // ═══════════════════════════════════════════════ TIPS SLICING ════════════════════════════════════════════════════\n\n    /// @notice Returns summitTip field\n    function summitTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_SUMMIT_TIP);\n    }\n\n    /// @notice Returns attestationTip field\n    function attestationTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_ATTESTATION_TIP);\n    }\n\n    /// @notice Returns executionTip field\n    function executionTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_EXECUTION_TIP);\n    }\n\n    /// @notice Returns deliveryTip field\n    function deliveryTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips));\n    }\n\n    // ════════════════════════════════════════════════ TIPS VALUE ═════════════════════════════════════════════════════\n\n    /// @notice Returns total value of the tips payload.\n    /// This is the sum of the encoded values, scaled up by TIPS_MULTIPLIER\n    function value(Tips tips) internal pure returns (uint256 value_) {\n        value_ = uint256(tips.summitTip()) + tips.attestationTip() + tips.executionTip() + tips.deliveryTip();\n        value_ \u003c\u003c= TIPS_GRANULARITY;\n    }\n\n    /// @notice Increases the delivery tip to match the new value.\n    function matchValue(Tips tips, uint256 newValue) internal pure returns (Tips newTips) {\n        uint256 oldValue = tips.value();\n        if (newValue \u003c oldValue) revert TipsValueTooLow();\n        // We want to increase the delivery tip, while keeping the other tips the same\n        unchecked {\n            uint256 delta = (newValue - oldValue) \u003e\u003e TIPS_GRANULARITY;\n            // `delta` fits into uint224, as TIPS_GRANULARITY is 32, so this never overflows uint256.\n            // In practice, this will never overflow uint64 as well, but we still check it just in case.\n            if (delta + tips.deliveryTip() \u003e type(uint64).max) revert TipsOverflow();\n            // Delivery tips occupy lowest 8 bytes, so we can just add delta to the tips value\n            // to effectively increase the delivery tip (knowing that delta fits into uint64).\n            newTips = Tips.wrap(Tips.unwrap(tips) + delta);\n        }\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    function __Ownable_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable_init_unchained() internal onlyInitializing {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n    function __Ownable2Step_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable2Step_init_unchained() internal onlyInitializing {\n    }\n    address private _pendingOwner;\n\n    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Returns the address of the pending owner.\n     */\n    function pendingOwner() public view virtual returns (address) {\n        return _pendingOwner;\n    }\n\n    /**\n     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual override onlyOwner {\n        _pendingOwner = newOwner;\n        emit OwnershipTransferStarted(owner(), newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual override {\n        delete _pendingOwner;\n        super._transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev The new owner accepts the ownership transfer.\n     */\n    function acceptOwnership() public virtual {\n        address sender = _msgSender();\n        require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n        _transferOwnership(sender);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// contracts/libs/memory/State.sol\n\n/// State is a memory view over a formatted state payload.\ntype State is uint256;\n\nusing StateLib for State global;\n\n/// # State\n/// State structure represents the state of Origin contract at some point of time.\n/// - State is structured in a way to track the updates of the Origin Merkle Tree.\n/// - State includes root of the Origin Merkle Tree, origin domain and some additional metadata.\n/// ## Origin Merkle Tree\n/// Hash of every sent message is inserted in the Origin Merkle Tree, which changes\n/// the value of Origin Merkle Root (which is the root for the mentioned tree).\n/// - Origin has a single Merkle Tree for all messages, regardless of their destination domain.\n/// - This leads to Origin state being updated if and only if a message was sent in a block.\n/// - Origin contract is a \"source of truth\" for states: a state is considered \"valid\" in its Origin,\n/// if it matches the state of the Origin contract after the N-th (nonce) message was sent.\n///\n/// # Memory layout of State fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                    |\n/// | ---------- | ----------- | ------- | ----- | ------------------------------ |\n/// | [000..032) | root        | bytes32 | 32    | Root of the Origin Merkle Tree |\n/// | [032..036) | origin      | uint32  | 4     | Domain where Origin is located |\n/// | [036..040) | nonce       | uint32  | 4     | Amount of sent messages        |\n/// | [040..045) | blockNumber | uint40  | 5     | Block of last sent message     |\n/// | [045..050) | timestamp   | uint40  | 5     | Time of last sent message      |\n/// | [050..062) | gasData     | uint96  | 12    | Gas data for the chain         |\n///\n/// @dev State could be used to form a Snapshot to be signed by a Guard or a Notary.\nlibrary StateLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_ROOT = 0;\n    uint256 private constant OFFSET_ORIGIN = 32;\n    uint256 private constant OFFSET_NONCE = 36;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 40;\n    uint256 private constant OFFSET_TIMESTAMP = 45;\n    uint256 private constant OFFSET_GAS_DATA = 50;\n\n    // ═══════════════════════════════════════════════════ STATE ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted State payload with provided fields\n     * @param root_         New merkle root\n     * @param origin_       Domain of Origin's chain\n     * @param nonce_        Nonce of the merkle root\n     * @param blockNumber_  Block number when root was saved in Origin\n     * @param timestamp_    Block timestamp when root was saved in Origin\n     * @param gasData_      Gas data for the chain\n     * @return Formatted state\n     */\n    function formatState(\n        bytes32 root_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_,\n        GasData gasData_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(root_, origin_, nonce_, blockNumber_, timestamp_, gasData_);\n    }\n\n    /**\n     * @notice Returns a State view over the given payload.\n     * @dev Will revert if the payload is not a state.\n     */\n    function castToState(bytes memory payload) internal pure returns (State) {\n        return castToState(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a State view.\n     * @dev Will revert if the memory view is not over a state.\n     */\n    function castToState(MemView memView) internal pure returns (State) {\n        if (!isState(memView)) revert UnformattedState();\n        return State.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted State.\n    function isState(MemView memView) internal pure returns (bool) {\n        return memView.len() == STATE_LENGTH;\n    }\n\n    /// @notice Returns the hash of a State, that could be later signed by a Guard to signal\n    /// that the state is invalid.\n    function hashInvalid(State state) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(stateInvalidSalt, keccak(state))\n        return state.unwrap().keccakSalted(STATE_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(State state) internal pure returns (MemView) {\n        return MemView.wrap(State.unwrap(state));\n    }\n\n    /// @notice Compares two State structures.\n    function equals(State a, State b) internal pure returns (bool) {\n        // Length of a State payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═══════════════════════════════════════════════ STATE HASHING ═══════════════════════════════════════════════════\n\n    /// @notice Returns the hash of the State.\n    /// @dev We are using the Merkle Root of a tree with two leafs (see below) as state hash.\n    function leaf(State state) internal pure returns (bytes32) {\n        (bytes32 leftLeaf_, bytes32 rightLeaf_) = state.subLeafs();\n        // Final hash is the parent of these leafs\n        return keccak256(bytes.concat(leftLeaf_, rightLeaf_));\n    }\n\n    /// @notice Returns \"sub-leafs\" of the State. Hash of these \"sub leafs\" is going to be used\n    /// as a \"state leaf\" in the \"Snapshot Merkle Tree\".\n    /// This enables proving that leftLeaf = (root, origin) was a part of the \"Snapshot Merkle Tree\",\n    /// by combining `rightLeaf` with the remainder of the \"Snapshot Merkle Proof\".\n    function subLeafs(State state) internal pure returns (bytes32 leftLeaf_, bytes32 rightLeaf_) {\n        MemView memView = state.unwrap();\n        // Left leaf is (root, origin)\n        leftLeaf_ = memView.prefix({len_: OFFSET_NONCE}).keccak();\n        // Right leaf is (metadata), or (nonce, blockNumber, timestamp)\n        rightLeaf_ = memView.sliceFrom({index_: OFFSET_NONCE}).keccak();\n    }\n\n    /// @notice Returns the left \"sub-leaf\" of the State.\n    function leftLeaf(bytes32 root_, uint32 origin_) internal pure returns (bytes32) {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(root_, origin_));\n    }\n\n    /// @notice Returns the right \"sub-leaf\" of the State.\n    function rightLeaf(uint32 nonce_, uint40 blockNumber_, uint40 timestamp_, GasData gasData_)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(nonce_, blockNumber_, timestamp_, gasData_));\n    }\n\n    // ═══════════════════════════════════════════════ STATE SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns a historical Merkle root from the Origin contract.\n    function root(State state) internal pure returns (bytes32) {\n        return state.unwrap().index({index_: OFFSET_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns domain of chain where the Origin contract is deployed.\n    function origin(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns nonce of Origin contract at the time, when `root` was the Merkle root.\n    function nonce(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when `root` was saved in Origin.\n    function blockNumber(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when `root` was saved in Origin.\n    /// @dev This is the timestamp according to the origin chain.\n    function timestamp(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n\n    /// @notice Returns gas data for the chain.\n    function gasData(State state) internal pure returns (GasData) {\n        return GasDataLib.wrapGasData(state.unwrap().indexUint({index_: OFFSET_GAS_DATA, bytes_: GAS_DATA_LENGTH}));\n    }\n}\n\n// contracts/libs/memory/BaseMessage.sol\n\n/// BaseMessage is a memory view over the base message supported by Origin-Destination\ntype BaseMessage is uint256;\n\nusing BaseMessageLib for BaseMessage global;\n\n/// BaseMessage structure represents a base message sent via the Origin-Destination contracts.\n/// - It only contains data relevant to the base message, the rest of data is encoded in the message header.\n/// - `sender` and `recipient` for EVM chains are EVM addresses casted to bytes32, while preserving left-alignment.\n/// - `tips` and `request` parameters are specified by a message sender\n/// \u003e Origin will calculate minimum tips for given request and content length, and will reject messages with tips\n/// lower than that.\n///\n/// # Memory layout of BaseMessage fields\n///\n/// | Position   | Field     | Type    | Bytes | Description                            |\n/// | ---------- | --------- | ------- | ----- | -------------------------------------- |\n/// | [000..032) | tips      | uint256 | 32    | Encoded tips paid on origin chain      |\n/// | [032..064) | sender    | bytes32 | 32    | Sender address on origin chain         |\n/// | [064..096) | recipient | bytes32 | 32    | Recipient address on destination chain |\n/// | [096..116) | request   | uint160 | 20    | Encoded request for message execution  |\n/// | [104..AAA) | content   | bytes   | ??    | Content to be passed to recipient      |\nlibrary BaseMessageLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_TIPS = 0;\n    uint256 private constant OFFSET_SENDER = 32;\n    uint256 private constant OFFSET_RECIPIENT = 64;\n    uint256 private constant OFFSET_REQUEST = OFFSET_RECIPIENT + TIPS_LENGTH;\n    uint256 private constant OFFSET_CONTENT = OFFSET_REQUEST + REQUEST_LENGTH;\n\n    // ═══════════════════════════════════════════════ BASE MESSAGE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted BaseMessage payload with provided fields.\n     * @param tips_         Encoded tips information\n     * @param sender_       Sender address on origin chain\n     * @param recipient_    Recipient address on destination chain\n     * @param request_      Encoded request for message execution\n     * @param content_      Raw content to be passed to recipient on destination chain\n     * @return Formatted base message\n     */\n    function formatBaseMessage(Tips tips_, bytes32 sender_, bytes32 recipient_, Request request_, bytes memory content_)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return abi.encodePacked(tips_, sender_, recipient_, request_, content_);\n    }\n\n    /**\n     * @notice Returns a BaseMessage view over the given payload.\n     * @dev Will revert if the payload is not a base message.\n     */\n    function castToBaseMessage(bytes memory payload) internal pure returns (BaseMessage) {\n        return castToBaseMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a BaseMessage view.\n     * @dev Will revert if the memory view is not over a base message payload.\n     */\n    function castToBaseMessage(MemView memView) internal pure returns (BaseMessage) {\n        if (!isBaseMessage(memView)) revert UnformattedBaseMessage();\n        return BaseMessage.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted BaseMessage.\n    function isBaseMessage(MemView memView) internal pure returns (bool) {\n        // Check if sender, recipient, tips fields exist\n        return (memView.len() \u003e= OFFSET_CONTENT);\n        // Content could be empty, so we don't check that\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(BaseMessage baseMessage) internal pure returns (MemView) {\n        return MemView.wrap(BaseMessage.unwrap(baseMessage));\n    }\n\n    /// @notice Returns baseMessage's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        // We hash \"tips\" and \"everything but tips\" to make tips proofs easier to verify\n        return MerkleMath.getParent(baseMessage.tips().leaf(), baseMessage.bodyLeaf());\n    }\n\n    /// @notice Returns hash for the \"everything but tips\" part of the base message.\n    function bodyLeaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_SENDER}).keccak();\n    }\n\n    // ═══════════════════════════════════════════ BASE MESSAGE SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips paid on origin chain.\n    function tips(BaseMessage baseMessage) internal pure returns (Tips) {\n        return TipsLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_TIPS, bytes_: TIPS_LENGTH})));\n    }\n\n    /// @notice Returns sender address on origin chain.\n    function sender(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_SENDER, bytes_: 32});\n    }\n\n    /// @notice Returns recipient address on destination chain.\n    function recipient(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_RECIPIENT, bytes_: 32});\n    }\n\n    /// @notice Returns an encoded request for message execution on destination chain.\n    function request(BaseMessage baseMessage) internal pure returns (Request) {\n        return RequestLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_REQUEST, bytes_: REQUEST_LENGTH})));\n    }\n\n    /// @notice Returns an untyped memory view over the content to be passed to recipient.\n    function content(BaseMessage baseMessage) internal pure returns (MemView) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_CONTENT});\n    }\n}\n\n// contracts/base/MessagingBase.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for all messaging contracts.\n * - Provides context on the local chain's domain.\n * - Provides ownership functionality.\n * - Will be providing pausing functionality when it is implemented.\n */\nabstract contract MessagingBase is MultiCallable, Versioned, Ownable2StepUpgradeable {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @notice Domain of the local chain, set once upon contract creation\n    uint32 public immutable localDomain;\n    // @notice Domain of the Synapse chain, set once upon contract creation\n    uint32 public immutable synapseDomain;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev gap for upgrade safety\n    uint256[50] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    constructor(string memory version_, uint32 synapseDomain_) Versioned(version_) {\n        localDomain = ChainContext.chainId();\n        synapseDomain = synapseDomain_;\n    }\n\n    // TODO: Implement pausing\n\n    /**\n     * @dev Should be impossible to renounce ownership;\n     * we override OpenZeppelin OwnableUpgradeable's\n     * implementation of renounceOwnership to make it a no-op\n     */\n    function renounceOwnership() public override onlyOwner {} //solhint-disable-line no-empty-blocks\n}\n\n// contracts/libs/memory/Message.sol\n\n/// Message is a memory over over a formatted message payload.\ntype Message is uint256;\n\nusing MessageLib for Message global;\n\n/// Library for formatting the various messages supported by Origin and Destination.\n///\n/// # Message memory layout\n///\n/// | Position   | Field  | Type    | Bytes | Description                                             |\n/// | ---------- | ------ | ------- | ----- | ------------------------------------------------------- |\n/// | [000..017) | header | uint136 | 17    | Encoded general routing information for the message     |\n/// | [017..AAA) | body   | bytes   | ??    | Formatted payload (according to flag) with message body |\nlibrary MessageLib {\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MemViewLib for bytes;\n    using HeaderLib for MemView;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_HEADER = 0;\n    uint256 private constant OFFSET_BODY = OFFSET_HEADER + HEADER_LENGTH;\n\n    // ══════════════════════════════════════════════════ MESSAGE ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns formatted message with provided fields.\n     * @param header_   Encoded general routing information for the message\n     * @param body_     Formatted payload (according to flag) with message body\n     * @return Formatted message\n     */\n    function formatMessage(Header header_, bytes memory body_) internal pure returns (bytes memory) {\n        return abi.encodePacked(header_, body_);\n    }\n\n    /**\n     * @notice Returns a Message view over for the given payload.\n     * @dev Will revert if the payload is not a message payload.\n     */\n    function castToMessage(bytes memory payload) internal pure returns (Message) {\n        return castToMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Message view.\n     * @dev Will revert if the memory view is not over a message payload.\n     */\n    function castToMessage(MemView memView) internal pure returns (Message) {\n        if (!isMessage(memView)) revert UnformattedMessage();\n        return Message.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Message.\n     */\n    function isMessage(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Check if headers exist in the payload\n        if (length \u003c OFFSET_BODY) return false;\n        // Check that Header is valid\n        uint256 paddedHeader = _header(memView);\n        if (!HeaderLib.isHeader(paddedHeader)) return false;\n        // Check that body is formatted according to the flag\n        // Only Base/Manager message flags exist\n        if (HeaderLib.wrapPadded(paddedHeader).flag() == MessageFlag.Base) {\n            // Check if body is a formatted base message\n            return _body(memView).isBaseMessage();\n        } else {\n            // Check if body is a formatted calldata for AgentManager call\n            return _body(memView).isCallData();\n        }\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Message message) internal pure returns (MemView) {\n        return MemView.wrap(Message.unwrap(message));\n    }\n\n    /// @notice Returns message's hash: a leaf to be inserted in the Merkle tree.\n    function leaf(Message message) internal pure returns (bytes32) {\n        // We hash header and body separately to make message proofs easier to verify\n        Header header_ = message.header();\n        // Only Base/Manager message flags exist\n        if (header_.flag() == MessageFlag.Base) {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToBaseMessage().leaf());\n        } else {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToCallData().leaf());\n        }\n    }\n\n    // ══════════════════════════════════════════════ MESSAGE SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns message's encoded header field.\n    function header(Message message) internal pure returns (Header) {\n        return HeaderLib.wrapPadded((message.unwrap().indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH})));\n    }\n\n    /// @notice Returns message's body field as an untyped memory view.\n    function body(Message message) internal pure returns (MemView) {\n        MemView memView = message.unwrap();\n        return _body(memView);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns message's padded header without checking that it is a valid header.\n    function _header(MemView memView) private pure returns (uint256) {\n        return memView.indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH});\n    }\n\n    /// @dev Returns an untyped memory view over the body field without checking\n    /// if the whole payload or the body are properly formatted.\n    function _body(MemView memView) private pure returns (MemView) {\n        return memView.sliceFrom({index_: OFFSET_BODY});\n    }\n}\n\n// contracts/base/AgentSecured.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for messaging contracts that are secured by the agent manager.\n * `AgentSecured` relies on `AgentManager` to provide the following functionality:\n * - Keep track of agents and their statuses.\n * - Pass agent-signed statements that were verified by the agent manager.\n * - These statements are considered valid indefinitely, unless the agent is disputed.\n * - Disputes are opened and resolved by the agent manager.\n * \u003e `AgentSecured` implementation should never use statements signed by agents that are disputed.\n */\nabstract contract AgentSecured is MessagingBase, IAgentSecured {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    address public immutable agentManager;\n\n    /// @inheritdoc IAgentSecured\n    address public immutable inbox;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    // (agent index =\u003e their dispute status: flag, openedAt, resolvedAt)\n    mapping(uint32 =\u003e DisputeStatus) internal _disputes;\n\n    /// @dev gap for upgrade safety\n    uint256[49] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    modifier onlyAgentManager() {\n        if (msg.sender != agentManager) revert CallerNotAgentManager();\n        _;\n    }\n\n    modifier onlyInbox() {\n        if (msg.sender != inbox) revert CallerNotInbox();\n        _;\n    }\n\n    constructor(string memory version_, uint32 synapseDomain_, address agentManager_, address inbox_)\n        MessagingBase(version_, synapseDomain_)\n    {\n        agentManager = agentManager_;\n        inbox = inbox_;\n    }\n\n    // ════════════════════════════════════════════ ONLY AGENT MANAGER ═════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external onlyAgentManager {\n        uint40 openedAt = ChainContext.blockTimestamp();\n        DisputeStatus memory status = DisputeStatus({flag: DisputeFlag.Pending, openedAt: openedAt, resolvedAt: 0});\n        _disputes[guardIndex] = status;\n        _disputes[notaryIndex] = status;\n    }\n\n    /// @inheritdoc IAgentSecured\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external onlyAgentManager {\n        // Update the dispute status of the slashed agent first.\n        uint40 resolvedAt = ChainContext.blockTimestamp();\n        _disputes[slashedIndex].flag = DisputeFlag.Slashed;\n        _disputes[slashedIndex].resolvedAt = resolvedAt;\n        // Mark the rival agent as not disputed, if there was an ongoing dispute.\n        if (rivalIndex != 0) {\n            _disputes[rivalIndex].flag = DisputeFlag.None;\n            _disputes[rivalIndex].resolvedAt = resolvedAt;\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function agentStatus(address agent) external view returns (AgentStatus memory) {\n        return _agentStatus(agent);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status) {\n        return _getAgent(index);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory) {\n        return _disputes[agentIndex];\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns status of the given agent: (flag, domain, index).\n    function _agentStatus(address agent) internal view returns (AgentStatus memory) {\n        return IAgentManager(agentManager).agentStatus(agent);\n    }\n\n    /// @dev Returns agent and their status for a given agent index. Returns zero values for non existing indexes.\n    function _getAgent(uint256 index) internal view returns (address agent, AgentStatus memory status) {\n        return IAgentManager(agentManager).getAgent(index);\n    }\n\n    /// @dev Checks if a Dispute exists for the given Notary. This function returns true, if\n    /// Notary is in ongoing Dispute, or if Dispute was resolved not in Notary's favor.\n    /// In both cases we can't trust Notary's data.\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeExists(uint32 notaryIndex) internal view returns (bool) {\n        return _disputes[notaryIndex].flag != DisputeFlag.None;\n    }\n\n    /// @dev Checks if a Notary recently won a Dispute and is still in the \"post-dispute\" timeout period.\n    /// In this period we still can't trust Notary's data, though we can optimistically assume that\n    /// that the data will be correct after the timeout (assuming no new Disputes are opened).\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeTimeout(uint32 notaryIndex) internal view returns (bool) {\n        DisputeStatus memory status = _disputes[notaryIndex];\n        // Exit early if Notary is in ongoing Dispute / slashed.\n        if (status.flag != DisputeFlag.None) return false;\n        // Check if Notary has been in any Dispute at all.\n        if (status.openedAt == 0) return false;\n        // Otherwise check if the Dispute timeout is still active.\n        return block.timestamp \u003c status.resolvedAt + DISPUTE_TIMEOUT_NOTARY;\n    }\n}\n\n// contracts/hubs/StateHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StateHub` is a parent contract for `Origin`. It is responsible for the following:\n/// - Keeping track of the historical Origin Merkle Tree containing all the message hashes.\n/// - Keeping track of the historical Origin States, as well as verifying their validity.\nabstract contract StateHub is AgentSecured, StateHubEvents, IStateHub {\n    using SafeCast for uint256;\n    using StateLib for bytes;\n\n    struct OriginState {\n        uint40 blockNumber;\n        uint40 timestamp;\n        GasData gasData;\n    }\n    // Bits left for tight packing: 80\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Historical Merkle Tree\n    /// Note: Takes two storage slots\n    HistoricalTree private _tree;\n\n    /// @dev All historical contract States\n    OriginState[] private _originStates;\n\n    /// @dev gap for upgrade safety\n    uint256[47] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IStateHub\n    function isValidState(bytes memory statePayload) external view returns (bool isValid) {\n        // This will revert if payload is not a formatted state\n        State state = statePayload.castToState();\n        return _isValidState(state);\n    }\n\n    /// @inheritdoc IStateHub\n    function statesAmount() external view returns (uint256) {\n        return _originStates.length;\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestLatestState() external view returns (bytes memory stateData) {\n        // This never underflows, assuming the contract was initialized\n        return suggestState(_nextNonce() - 1);\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestState(uint32 nonce) public view returns (bytes memory stateData) {\n        // This will revert if nonce is out of range\n        bytes32 root = _tree.root(nonce);\n        return _formatOriginState(_originStates[nonce], root, localDomain, nonce);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Initializes the saved states list by inserting a state for an empty Merkle Tree.\n    function _initializeStates() internal {\n        // This should only be called once, when the contract is initialized\n        // This will revert if _tree.roots is non-empty\n        bytes32 savedRoot = _tree.initializeRoots();\n        // Save root for empty merkle _tree with block number and timestamp of initialization\n        _saveState(savedRoot, _toOriginState());\n    }\n\n    /// @dev Inserts leaf into the Merkle Tree and saves the updated origin State.\n    function _insertAndSave(bytes32 leaf) internal {\n        bytes32 newRoot = _tree.insert(leaf);\n        _saveState(newRoot, _toOriginState());\n    }\n\n    /// @dev Saves an updated state of the Origin contract\n    function _saveState(bytes32 root, OriginState memory state) internal {\n        uint32 nonce = _nextNonce();\n        _originStates.push(state);\n        // Emit event with raw state data\n        emit StateSaved(_formatOriginState(state, root, localDomain, nonce));\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns nonce of the next sent message: the amount of saved States so far.\n    /// This always equals to \"total amount of sent messages\" plus 1.\n    function _nextNonce() internal view returns (uint32) {\n        // TODO: consider using more than 32 bits for origin nonces\n        return _originStates.length.toUint32();\n    }\n\n    /// @dev Checks if a state is valid, i.e. if it matches the historical one.\n    /// Reverts, if state refers to another Origin contract.\n    function _isValidState(State state) internal view returns (bool) {\n        // Check if state refers to this contract\n        if (state.origin() != localDomain) revert IncorrectOriginDomain();\n        // Check if nonce exists\n        uint32 nonce = state.nonce();\n        if (nonce \u003e= _originStates.length) return false;\n        // Check if state root matches the historical one\n        if (state.root() != _tree.root(nonce)) return false;\n        // Check if state metadata matches the historical one\n        return _areEqual(state, _originStates[nonce]);\n    }\n\n    // ═════════════════════════════════════════════ STRUCT FORMATTING ═════════════════════════════════════════════════\n\n    /// @dev Returns a formatted payload for a stored OriginState.\n    function _formatOriginState(OriginState memory originState, bytes32 root, uint32 origin, uint32 nonce)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return StateLib.formatState({\n            root_: root,\n            origin_: origin,\n            nonce_: nonce,\n            blockNumber_: originState.blockNumber,\n            timestamp_: originState.timestamp,\n            gasData_: originState.gasData\n        });\n    }\n\n    /// @dev Child contract should implement the logic for getting the current gas data from the gas oracle\n    /// to be saved as part of the Origin State.\n    // solhint-disable-next-line ordering\n    function _fetchGasData() internal view virtual returns (GasData);\n\n    /// @dev Returns a OriginState struct to save in the contract.\n    function _toOriginState() internal view returns (OriginState memory originState) {\n        originState.blockNumber = ChainContext.blockNumber();\n        originState.timestamp = ChainContext.blockTimestamp();\n        originState.gasData = _fetchGasData();\n    }\n\n    /// @dev Checks that a state and its Origin representation are equal.\n    function _areEqual(State state, OriginState memory originState) internal pure returns (bool) {\n        return state.blockNumber() == originState.blockNumber \u0026\u0026 state.timestamp() == originState.timestamp;\n    }\n}\n\n// contracts/Origin.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Origin` contract is used for sending messages to remote chains. It is done\n/// by inserting the message hashes into the Origin Merkle, which makes it possible to\n/// prove that message was sent using the Merkle proof against the Origin Merkle Root. This essentially\n/// compresses the list of messages into a single 32-byte value that needs to be stored on the destination chain.\n/// `Origin` is responsible for the following:\n/// - Formatting the sent message payloads, and inserting their hashes into the Origin Merkle Tree.\n/// - Keeping track of its own historical states (see parent contract `StateHub`).\n/// - Enforcing minimum tip values for sent base messages based on the provided execution requests.\n/// - Distributing the collected tips upon request from a local `AgentManager` contract.\ncontract Origin is StateHub, OriginEvents, InterfaceOrigin {\n    using MemViewLib for bytes;\n    using MessageLib for bytes;\n    using TipsLib for bytes;\n    using TypeCasts for address;\n\n    address public immutable gasOracle;\n\n    modifier onlyRemoteDestination(uint32 destination) {\n        if (destination == localDomain) revert IncorrectDestinationDomain();\n        _;\n    }\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_, address gasOracle_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {\n        gasOracle = gasOracle_;\n    }\n\n    /// @notice Initializes Origin contract:\n    /// - msg.sender is set as contract owner\n    /// - State of \"empty merkle tree\" is saved\n    function initialize() external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize \"states\": state of an \"empty merkle tree\" is saved\n        _initializeStates();\n    }\n\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable onlyRemoteDestination(destination) returns (uint32 messageNonce, bytes32 messageHash) {\n        // Check that content is not too large\n        if (content.length \u003e MAX_CONTENT_BYTES) revert ContentLengthTooBig();\n        // This will revert if msg.value is lower than value of minimum tips\n        Tips tips = _getMinimumTips(destination, paddedRequest, content.length).matchValue(msg.value);\n        Request request = RequestLib.wrapPadded(paddedRequest);\n        // Format the BaseMessage body\n        bytes memory body = BaseMessageLib.formatBaseMessage({\n            sender_: msg.sender.addressToBytes32(),\n            recipient_: recipient,\n            tips_: tips,\n            request_: request,\n            content_: content\n        });\n        // Send the message\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Base, body);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        onlyAgentManager\n        onlyRemoteDestination(destination)\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // AgentManager (checked via modifier) is responsible for constructing the calldata payload correctly.\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Manager, payload);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function withdrawTips(address recipient, uint256 amount) external onlyAgentManager {\n        if (address(this).balance \u003c amount) revert InsufficientEthBalance();\n        (bool success,) = recipient.call{value: amount}(\"\");\n        if (!success) revert EthTransferFailed();\n        emit TipWithdrawalCompleted(recipient, amount);\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue)\n    {\n        return _getMinimumTips(destination, paddedRequest, contentLength).value();\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Sends the given message to the specified destination. Message hash is inserted\n    /// into the Origin Merkle Tree, which will enable message execution on destination chain.\n    function _sendMessage(uint32 destination, uint32 optimisticPeriod, MessageFlag flag, bytes memory body)\n        internal\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // Format the message header\n        messageNonce = _nextNonce();\n        Header header = flag.encodeHeader({\n            origin_: localDomain,\n            nonce_: messageNonce,\n            destination_: destination,\n            optimisticPeriod_: optimisticPeriod\n        });\n        // Format the full message payload\n        bytes memory msgPayload = MessageLib.formatMessage(header, body);\n        // Insert new leaf into the Origin Merkle Tree and save the updated state\n        messageHash = msgPayload.castToMessage().leaf();\n        _insertAndSave(messageHash);\n        // Emit event with message information\n        emit Sent(messageHash, messageNonce, destination, msgPayload);\n        // Update the gas oracle data. We do this after the provided tips are checked so that\n        // the provided message is sent in the event that the gas oracle data is updated to a higher value.\n        InterfaceGasOracle(gasOracle).updateGasData(destination);\n        // TODO: consider doing this before the message is sent, while adjusting GasOracle.getMinimumTips() to\n        // use the pending gas oracle data.\n    }\n\n    /// @dev Returns the minimum tips for sending a message to the given destination with the given request and content.\n    function _getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        internal\n        view\n        returns (Tips)\n    {\n        return\n            TipsLib.wrapPadded(InterfaceGasOracle(gasOracle).getMinimumTips(destination, paddedRequest, contentLength));\n    }\n\n    /// @dev Gets the current gas data from the gas oracle to be saved as part of the Origin State.\n    function _fetchGasData() internal view override returns (GasData) {\n        return GasDataLib.wrapGasData(InterfaceGasOracle(gasOracle).getGasData());\n    }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"18465:350:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;18465:350:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"18465:350:0:-:0;;;;;;;;","abiDefinition":[],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Origin.sol\":\"TypeCasts\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Origin.sol\":{\"keccak256\":\"0x96775924f147f3d1f8df8cdf56731fe52a15af8d8e12e608efb8158c112b18cd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e642a27f5fab3c62b4c02e9754e9e42b1cf2e5381dbea9d3d106d23b7772ebe6\",\"dweb:/ipfs/QmUwn7ZyBvPkjnMuK8ZMSexBUdNQnVtxwyoAyT4DXLQjra\"]}},\"version\":1}"},"hashes":{}},"solidity/Origin.sol:Versioned":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/OriginEvents.sol\n\n/// @notice A collection of events emitted by the Origin contract\nabstract contract OriginEvents {\n    /**\n     * @notice Emitted when a new message is sent.\n     * @param messageHash   Hash of message; the leaf inserted to the Merkle tree for the message\n     * @param nonce         Nonce of sent message (starts from 1)\n     * @param destination   Destination domain\n     * @param message       Raw bytes of message\n     */\n    event Sent(bytes32 indexed messageHash, uint32 indexed nonce, uint32 indexed destination, bytes message);\n\n    /**\n     * @notice Emitted when a tip withdrawal is completed.\n     * @param actor     Actor address\n     * @param tip       Tip value, denominated in local domain's wei\n     */\n    event TipWithdrawalCompleted(address actor, uint256 tip);\n}\n\n// contracts/events/StateHubEvents.sol\n\n/// @notice A collection of events emitted by the StateHub contract\nabstract contract StateHubEvents {\n    /**\n     * @notice Emitted when a new Origin State is saved after a message was sent.\n     * @param state     Raw payload with state data\n     */\n    event StateSaved(bytes state);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n    /**\n     * @notice Check that a given state is valid: matches the historical state of Origin contract.\n     * Note: any Agent including an invalid state in their snapshot will be slashed\n     * upon providing the snapshot and agent signature for it to Origin contract.\n     * @dev Will revert if any of these is true:\n     *  - State payload is not properly formatted.\n     * @param statePayload      Raw payload with state data\n     * @return isValid          Whether the provided state is valid\n     */\n    function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n    /**\n     * @notice Returns the amount of saved states so far.\n     * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n     */\n    function statesAmount() external view returns (uint256);\n\n    /**\n     * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @return statePayload     Raw payload with the latest state data\n     */\n    function suggestLatestState() external view returns (bytes memory statePayload);\n\n    /**\n     * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n     * Note: signing the suggested state data will will never lead to slashing of the actor,\n     * assuming they have confirmed that the block, which number is included in the data,\n     * is not subject to reorganization (which is different for every observed chain).\n     * @param nonce             Historical nonce to form a state\n     * @return statePayload     Raw payload with historical state data\n     */\n    function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/InterfaceGasOracle.sol\n\ninterface InterfaceGasOracle {\n    /**\n     * @notice Fetches the latest gas data for the chain from `Destination` contract,\n     * and uses it to update the oracle values for the requested chain.\n     * @param domain    Domain to update the gas data for\n     */\n    function updateGasData(uint32 domain) external;\n\n    /**\n     * @notice Returns the gas data for the local chain.\n     */\n    function getGasData() external view returns (uint256 paddedGasData);\n\n    /**\n     * @notice Returns the gas data for the given domain, in the decoded format.\n     * @param domain        Domain of chain to get gas data for\n     * @return gasPrice     Gas price for the chain (in Wei per gas unit)\n     * @return dataPrice    Calldata price (in Wei per byte of content)\n     * @return execBuffer   Tx fee safety buffer for message execution (in Wei)\n     * @return amortAttCost Amortized cost for attestation submission (in Wei)\n     * @return etherPrice   Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n     * @return markup       Markup for the message execution (in BWAD)\n     */\n    function getDecodedGasData(uint32 domain)\n        external\n        view\n        returns (\n            uint256 gasPrice,\n            uint256 dataPrice,\n            uint256 execBuffer,\n            uint256 amortAttCost,\n            uint256 etherPrice,\n            uint256 markup\n        );\n\n    /**\n     * @notice Returns the minimum tips for sending a message to a given destination.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return paddedTips       Padded encoded minimum tips information\n     */\n    function getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 paddedTips);\n}\n\n// contracts/interfaces/InterfaceOrigin.sol\n\ninterface InterfaceOrigin {\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /**\n     * @notice Send a message to the recipient located on destination domain.\n     * @dev Recipient has to conform to IMessageRecipient interface, otherwise message won't be delivered.\n     * Will revert if any of these is true:\n     * - `destination` is equal to contract's local domain\n     * - `content` length is greater than `MAX_CONTENT_BYTES`\n     * - `msg.value` is lower than value of minimum tips for the given message\n     * @param destination           Domain of destination chain\n     * @param recipient             Address of recipient on destination chain as bytes32\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param paddedRequest         Padded encoded message execution request on destination chain\n     * @param content               Raw bytes content of message\n     * @return messageNonce         Nonce of the sent message\n     * @return messageHash          Hash of the sent message\n     */\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable returns (uint32 messageNonce, bytes32 messageHash);\n\n    /**\n     * @notice Send a manager message to the destination domain.\n     * @dev This could only be called by AgentManager, which takes care of encoding the calldata payload.\n     * Note: (msgOrigin, proofMaturity) security args will be added to payload on the destination chain\n     * so that the AgentManager could verify where the Manager Message came from and how mature is the proof.\n     * Note: function is not payable, as no tips are required for sending a manager message.\n     * Will revert if `destination` is equal to contract's local domain.\n     * @param destination           Domain of destination chain\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param payload               Payload for calling AgentManager on destination chain (with extra security args)\n     */\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        returns (uint32 messageNonce, bytes32 messageHash);\n\n    // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Withdraws locked base message tips to the recipient.\n     * @dev Could only be called by a local AgentManager.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function withdrawTips(address recipient, uint256 amount) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the minimum tips value for sending a message to a given destination.\n     * @dev Using at least `tipsValue` as `msg.value` for `sendBaseMessage()`\n     * will guarantee that the message will be accepted.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return tipsValue        Minimum tips value for a message to be accepted\n     */\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue);\n}\n\n// contracts/libs/Constants.sol\n\n// Here we define common constants to enable their easier reusing later.\n\n// ══════════════════════════════════ MERKLE ═══════════════════════════════════\n/// @dev Height of the Agent Merkle Tree\nuint256 constant AGENT_TREE_HEIGHT = 32;\n/// @dev Height of the Origin Merkle Tree\nuint256 constant ORIGIN_TREE_HEIGHT = 32;\n/// @dev Height of the Snapshot Merkle Tree. Allows up to 64 leafs, e.g. up to 32 states\nuint256 constant SNAPSHOT_TREE_HEIGHT = 6;\n// ══════════════════════════════════ STRUCTS ══════════════════════════════════\n/// @dev See Attestation.sol: (bytes32,bytes32,uint32,uint40,uint40): 32+32+4+5+5\nuint256 constant ATTESTATION_LENGTH = 78;\n/// @dev See GasData.sol: (uint16,uint16,uint16,uint16,uint16,uint16): 2+2+2+2+2+2\nuint256 constant GAS_DATA_LENGTH = 12;\n/// @dev See Receipt.sol: (uint32,uint32,bytes32,bytes32,uint8,address,address,address): 4+4+32+32+1+20+20+20\nuint256 constant RECEIPT_LENGTH = 133;\n/// @dev See State.sol: (bytes32,uint32,uint32,uint40,uint40,GasData): 32+4+4+5+5+len(GasData)\nuint256 constant STATE_LENGTH = 50 + GAS_DATA_LENGTH;\n/// @dev Maximum amount of states in a single snapshot. Each state produces two leafs in the tree\nuint256 constant SNAPSHOT_MAX_STATES = 1 \u003c\u003c (SNAPSHOT_TREE_HEIGHT - 1);\n// ══════════════════════════════════ MESSAGE ══════════════════════════════════\n/// @dev See Header.sol: (uint8,uint32,uint32,uint32,uint32): 1+4+4+4+4\nuint256 constant HEADER_LENGTH = 17;\n/// @dev See Request.sol: (uint96,uint64,uint32): 12+8+4\nuint256 constant REQUEST_LENGTH = 24;\n/// @dev See Tips.sol: (uint64,uint64,uint64,uint64): 8+8+8+8\nuint256 constant TIPS_LENGTH = 32;\n/// @dev The amount of discarded last bits when encoding tip values\nuint256 constant TIPS_GRANULARITY = 32;\n/// @dev Tip values could be only the multiples of TIPS_MULTIPLIER\nuint256 constant TIPS_MULTIPLIER = 1 \u003c\u003c TIPS_GRANULARITY;\n// ══════════════════════════════ STATEMENT SALTS ══════════════════════════════\n/// @dev Salts for signing various statements\nbytes32 constant ATTESTATION_VALID_SALT = keccak256(\"ATTESTATION_VALID_SALT\");\nbytes32 constant ATTESTATION_INVALID_SALT = keccak256(\"ATTESTATION_INVALID_SALT\");\nbytes32 constant RECEIPT_VALID_SALT = keccak256(\"RECEIPT_VALID_SALT\");\nbytes32 constant RECEIPT_INVALID_SALT = keccak256(\"RECEIPT_INVALID_SALT\");\nbytes32 constant SNAPSHOT_VALID_SALT = keccak256(\"SNAPSHOT_VALID_SALT\");\nbytes32 constant STATE_INVALID_SALT = keccak256(\"STATE_INVALID_SALT\");\n// ═════════════════════════════════ PROTOCOL ══════════════════════════════════\n/// @dev Optimistic period for new agent roots in LightManager\nuint32 constant AGENT_ROOT_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Timeout between the agent root could be proposed and resolved in LightManager\nuint32 constant AGENT_ROOT_PROPOSAL_TIMEOUT = 12 hours;\nuint32 constant BONDING_OPTIMISTIC_PERIOD = 1 days;\n/// @dev Amount of time that the Notary will not be considered active after they won a dispute\nuint32 constant DISPUTE_TIMEOUT_NOTARY = 12 hours;\n/// @dev Amount of time without fresh data from Notaries before contract owner can resolve stuck disputes manually\nuint256 constant FRESH_DATA_TIMEOUT = 4 hours;\n/// @dev Maximum bytes per message = 2 KiB (somewhat arbitrarily set to begin)\nuint256 constant MAX_CONTENT_BYTES = 2 * 2 ** 10;\n/// @dev Maximum value for the summit tip that could be set in GasOracle\nuint256 constant MAX_SUMMIT_TIP = 0.01 ether;\n\n// contracts/libs/Errors.sol\n\n// ══════════════════════════════ INVALID CALLER ═══════════════════════════════\n\nerror CallerNotAgentManager();\nerror CallerNotDestination();\nerror CallerNotInbox();\nerror CallerNotSummit();\n\n// ══════════════════════════════ INCORRECT DATA ═══════════════════════════════\n\nerror IncorrectAttestation();\nerror IncorrectAgentDomain();\nerror IncorrectAgentIndex();\nerror IncorrectAgentProof();\nerror IncorrectAgentRoot();\nerror IncorrectDataHash();\nerror IncorrectDestinationDomain();\nerror IncorrectOriginDomain();\nerror IncorrectSnapshotProof();\nerror IncorrectSnapshotRoot();\nerror IncorrectState();\nerror IncorrectStatesAmount();\nerror IncorrectTipsProof();\nerror IncorrectVersionLength();\n\nerror IncorrectNonce();\nerror IncorrectSender();\nerror IncorrectRecipient();\n\nerror FlagOutOfRange();\nerror IndexOutOfRange();\nerror NonceOutOfRange();\n\nerror OutdatedNonce();\n\nerror UnformattedAttestation();\nerror UnformattedAttestationReport();\nerror UnformattedBaseMessage();\nerror UnformattedCallData();\nerror UnformattedCallDataPrefix();\nerror UnformattedMessage();\nerror UnformattedReceipt();\nerror UnformattedReceiptReport();\nerror UnformattedSignature();\nerror UnformattedSnapshot();\nerror UnformattedState();\nerror UnformattedStateReport();\n\n// ═══════════════════════════════ MERKLE TREES ════════════════════════════════\n\nerror LeafNotProven();\nerror MerkleTreeFull();\nerror NotEnoughLeafs();\nerror TreeHeightTooLow();\n\n// ═════════════════════════════ OPTIMISTIC PERIOD ═════════════════════════════\n\nerror BaseClientOptimisticPeriod();\nerror MessageOptimisticPeriod();\nerror SlashAgentOptimisticPeriod();\nerror WithdrawTipsOptimisticPeriod();\nerror ZeroProofMaturity();\n\n// ═══════════════════════════════ AGENT MANAGER ═══════════════════════════════\n\nerror AgentNotGuard();\nerror AgentNotNotary();\n\nerror AgentCantBeAdded();\nerror AgentNotActive();\nerror AgentNotActiveNorUnstaking();\nerror AgentNotFraudulent();\nerror AgentNotUnstaking();\nerror AgentUnknown();\n\nerror AgentRootNotProposed();\nerror AgentRootTimeoutNotOver();\n\nerror NotStuck();\n\nerror DisputeAlreadyResolved();\nerror DisputeNotOpened();\nerror DisputeTimeoutNotOver();\nerror GuardInDispute();\nerror NotaryInDispute();\n\nerror MustBeSynapseDomain();\nerror SynapseDomainForbidden();\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\nerror AlreadyExecuted();\nerror AlreadyFailed();\nerror DuplicatedSnapshotRoot();\nerror IncorrectMagicValue();\nerror GasLimitTooLow();\nerror GasSuppliedTooLow();\n\n// ══════════════════════════════════ ORIGIN ═══════════════════════════════════\n\nerror ContentLengthTooBig();\nerror EthTransferFailed();\nerror InsufficientEthBalance();\n\n// ════════════════════════════════ GAS ORACLE ═════════════════════════════════\n\nerror LocalGasDataNotSet();\nerror RemoteGasDataNotSet();\n\n// ═══════════════════════════════════ TIPS ════════════════════════════════════\n\nerror SummitTipTooHigh();\nerror TipsClaimMoreThanEarned();\nerror TipsClaimZero();\nerror TipsOverflow();\nerror TipsValueTooLow();\n\n// ════════════════════════════════ MEMORY VIEW ════════════════════════════════\n\nerror IndexedTooMuch();\nerror ViewOverrun();\nerror OccupiedMemory();\nerror UnallocatedMemory();\nerror PrecompileOutOfGas();\n\n// ═════════════════════════════════ MULTICALL ═════════════════════════════════\n\nerror MulticallFailed();\n\n// contracts/libs/TypeCasts.sol\n\nlibrary TypeCasts {\n    // alignment preserving cast\n    function addressToBytes32(address addr) internal pure returns (bytes32) {\n        return bytes32(uint256(uint160(addr)));\n    }\n\n    // alignment preserving cast\n    function bytes32ToAddress(bytes32 buf) internal pure returns (address) {\n        return address(uint160(uint256(buf)));\n    }\n}\n\n// contracts/libs/stack/Number.sol\n\n/// Number is a compact representation of uint256, that is fit into 16 bits\n/// with the maximum relative error under 0.4%.\ntype Number is uint16;\n\nusing NumberLib for Number global;\n\n/// # Number\n/// Library for compact representation of uint256 numbers.\n/// - Number is stored using mantissa and exponent, each occupying 8 bits.\n/// - Numbers under 2**8 are stored as `mantissa` with `exponent = 0xFF`.\n/// - Numbers at least 2**8 are approximated as `(256 + mantissa) \u003c\u003c exponent`\n/// \u003e - `0 \u003c= mantissa \u003c 256`\n/// \u003e - `0 \u003c= exponent \u003c= 247` (`256 * 2**248` doesn't fit into uint256)\n/// # Number stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type  | Bytes |\n/// | ---------- | -------- | ----- | ----- |\n/// | (002..001] | mantissa | uint8 | 1     |\n/// | (001..000] | exponent | uint8 | 1     |\n\nlibrary NumberLib {\n    /// @dev Amount of bits to shift to mantissa field\n    uint16 private constant SHIFT_MANTISSA = 8;\n\n    /// @notice For bwad math (binary wad) we use 2**64 as \"wad\" unit.\n    /// @dev We are using not using 10**18 as wad, because it is not stored precisely in NumberLib.\n    uint256 internal constant BWAD_SHIFT = 64;\n    uint256 internal constant BWAD = 1 \u003c\u003c BWAD_SHIFT;\n    /// @notice ~0.1% in bwad units.\n    uint256 internal constant PER_MILLE_SHIFT = BWAD_SHIFT - 10;\n    uint256 internal constant PER_MILLE = 1 \u003c\u003c PER_MILLE_SHIFT;\n\n    /// @notice Compresses uint256 number into 16 bits.\n    function compress(uint256 value) internal pure returns (Number) {\n        // Find `msb` such as `2**msb \u003c= value \u003c 2**(msb + 1)`\n        uint256 msb = mostSignificantBit(value);\n        // We want to preserve 9 bits of precision.\n        // The highest bit is always 1, so we can skip it.\n        // The remaining 8 highest bits are stored as mantissa.\n        if (msb \u003c 8) {\n            // Value is less than 2**8, so we can use value as mantissa with \"-1\" exponent.\n            return _encode(uint8(value), 0xFF);\n        } else {\n            // We use `msb - 8` as exponent otherwise. Note that `exponent \u003e= 0`.\n            unchecked {\n                uint256 exponent = msb - 8;\n                // Shifting right by `msb-8` bits will shift the \"remaining 8 highest bits\" into the 8 lowest bits.\n                // uint8() will truncate the highest bit.\n                return _encode(uint8(value \u003e\u003e exponent), uint8(exponent));\n            }\n        }\n    }\n\n    /// @notice Decompresses 16 bits number into uint256.\n    /// @dev The outcome is an approximation of the original number: `(value - value / 256) \u003c number \u003c= value`.\n    function decompress(Number number) internal pure returns (uint256 value) {\n        // Isolate 8 highest bits as the mantissa.\n        uint256 mantissa = Number.unwrap(number) \u003e\u003e SHIFT_MANTISSA;\n        // This will truncate the highest bits, leaving only the exponent.\n        uint256 exponent = uint8(Number.unwrap(number));\n        if (exponent == 0xFF) {\n            return mantissa;\n        } else {\n            unchecked {\n                return (256 + mantissa) \u003c\u003c (exponent);\n            }\n        }\n    }\n\n    /// @dev Returns the most significant bit of `x`\n    /// https://solidity-by-example.org/bitwise/\n    function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\n        // To find `msb` we determine it bit by bit, starting from the highest one.\n        // `0 \u003c= msb \u003c= 255`, so we start from the highest bit, 1\u003c\u003c7 == 128.\n        // If `x` is at least 2**128, then the highest bit of `x` is at least 128.\n        // solhint-disable no-inline-assembly\n        assembly {\n            // `f` is set to 1\u003c\u003c7 if `x \u003e= 2**128` and to 0 otherwise.\n            let f := shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\n            // If `x \u003e= 2**128` then set `msb` highest bit to 1 and shift `x` right by 128.\n            // Otherwise, `msb` remains 0 and `x` remains unchanged.\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        // `x` is now at most 2**128 - 1. Continue the same way, the next highest bit is 1\u003c\u003c6 == 64.\n        assembly {\n            // `f` is set to 1\u003c\u003c6 if `x \u003e= 2**64` and to 0 otherwise.\n            let f := shl(6, gt(x, 0xFFFFFFFFFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c5 if `x \u003e= 2**32` and to 0 otherwise.\n            let f := shl(5, gt(x, 0xFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c4 if `x \u003e= 2**16` and to 0 otherwise.\n            let f := shl(4, gt(x, 0xFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c3 if `x \u003e= 2**8` and to 0 otherwise.\n            let f := shl(3, gt(x, 0xFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c2 if `x \u003e= 2**4` and to 0 otherwise.\n            let f := shl(2, gt(x, 0xF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c1 if `x \u003e= 2**2` and to 0 otherwise.\n            let f := shl(1, gt(x, 0x3))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1 if `x \u003e= 2**1` and to 0 otherwise.\n            let f := gt(x, 0x1)\n            msb := or(msb, f)\n        }\n    }\n\n    /// @dev Wraps (mantissa, exponent) pair into Number.\n    function _encode(uint8 mantissa, uint8 exponent) private pure returns (Number) {\n        // Casts below are upcasts, so they are safe.\n        return Number.wrap(uint16(mantissa) \u003c\u003c SHIFT_MANTISSA | uint16(exponent));\n    }\n}\n\n// contracts/libs/stack/Request.sol\n\n/// Request is encoded data with \"message execution request\".\ntype Request is uint192;\n\nusing RequestLib for Request global;\n\n/// Library for formatting _the request part_ of _the base messages_.\n/// - Request represents a message sender requirements for the message execution on the destination chain.\n/// - Request occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n/// \u003e gasDrop field is included for future compatibility and is ignored at the moment.\n///\n/// # Request stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type   | Bytes | Description                                          |\n/// | ---------- | -------- | ------ | ----- | ---------------------------------------------------- |\n/// | (024..012] | gasDrop  | uint96 | 12    | Minimum amount of gas token to drop to the recipient |\n/// | (012..004] | gasLimit | uint64 | 8     | Minimum amount of gas units to supply for execution  |\n/// | (004..000] | version  | uint32 | 4     | Base message version to pass to the recipient        |\n\nlibrary RequestLib {\n    /// @dev Amount of bits to shift to gasDrop field\n    uint192 private constant SHIFT_GAS_DROP = 12 * 8;\n    /// @dev Amount of bits to shift to gasLimit field\n    uint192 private constant SHIFT_GAS_LIMIT = 4 * 8;\n\n    /// @notice Returns an encoded request with the given fields\n    /// @param gasDrop_     Minimum amount of gas token to drop to the recipient (ignored at the moment)\n    /// @param gasLimit_    Minimum amount of gas units to supply for execution\n    /// @param version_     Base message version to pass to the recipient\n    function encodeRequest(uint96 gasDrop_, uint64 gasLimit_, uint32 version_) internal pure returns (Request) {\n        // Casts below are upcasts, so they are safe\n        return Request.wrap(uint192(gasDrop_) \u003c\u003c SHIFT_GAS_DROP | uint192(gasLimit_) \u003c\u003c SHIFT_GAS_LIMIT | version_);\n    }\n\n    /// @notice Wraps the padded encoded request into a Request-typed value.\n    /// @dev The \"padded\" request is simply an encoded request casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded requests\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedRequest) internal pure returns (Request) {\n        // Casting to uint192 will truncate the highest bits, which is the behavior we want\n        return Request.wrap(uint192(paddedRequest));\n    }\n\n    /// @notice Returns the requested of gas token to drop to the recipient.\n    function gasDrop(Request request) internal pure returns (uint96) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return uint96(Request.unwrap(request) \u003e\u003e SHIFT_GAS_DROP);\n    }\n\n    /// @notice Returns the requested minimum amount of gas units to supply for execution.\n    function gasLimit(Request request) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Request.unwrap(request) \u003e\u003e SHIFT_GAS_LIMIT);\n    }\n\n    /// @notice Returns the requested base message version to pass to the recipient.\n    function version(Request request) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Request.unwrap(request));\n    }\n}\n\n// node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        require(value \u003c= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        require(value \u003c= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        require(value \u003c= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value \u003c= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        require(value \u003c= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        require(value \u003c= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        require(value \u003c= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        require(value \u003c= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        require(value \u003c= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        require(value \u003c= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        require(value \u003c= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        require(value \u003c= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        require(value \u003c= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        require(value \u003c= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        require(value \u003c= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value \u003c= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        require(value \u003c= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        require(value \u003c= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        require(value \u003c= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value \u003c= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        require(value \u003c= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        require(value \u003c= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        require(value \u003c= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value \u003c= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        require(value \u003c= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        require(value \u003c= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        require(value \u003c= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value \u003c= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        require(value \u003c= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value \u003c= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value \u003c= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     *\n     * _Available since v3.0._\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value \u003e= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     *\n     * _Available since v3.0._\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value \u003c= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     *\n     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length \u003e 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance \u003e= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance \u003e= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length \u003e 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n\n// contracts/base/MultiCallable.sol\n\n/// @notice Collection of Multicall utilities. Fork of Multicall3:\n/// https://github.com/mds1/multicall/blob/master/src/Multicall3.sol\nabstract contract MultiCallable {\n    struct Call {\n        bool allowFailure;\n        bytes callData;\n    }\n\n    struct Result {\n        bool success;\n        bytes returnData;\n    }\n\n    /// @notice Aggregates a few calls to this contract into one multicall without modifying `msg.sender`.\n    function multicall(Call[] calldata calls) external returns (Result[] memory callResults) {\n        uint256 amount = calls.length;\n        callResults = new Result[](amount);\n        Call calldata call_;\n        for (uint256 i = 0; i \u003c amount;) {\n            call_ = calls[i];\n            Result memory result = callResults[i];\n            // We perform a delegate call to ourselves here. Delegate call does not modify `msg.sender`, so\n            // this will have the same effect as if `msg.sender` performed all the calls themselves one by one.\n            // solhint-disable-next-line avoid-low-level-calls\n            (result.success, result.returnData) = address(this).delegatecall(call_.callData);\n            // solhint-disable-next-line no-inline-assembly\n            assembly {\n                // Revert if the call fails and failure is not allowed\n                // `allowFailure := calldataload(call_)` and `success := mload(result)`\n                if iszero(or(calldataload(call_), mload(result))) {\n                    // Revert with `0x4d6a2328` (function selector for `MulticallFailed()`)\n                    mstore(0x00, 0x4d6a232800000000000000000000000000000000000000000000000000000000)\n                    revert(0x00, 0x04)\n                }\n            }\n            unchecked {\n                ++i;\n            }\n        }\n    }\n}\n\n// contracts/base/Version.sol\n\n/**\n * @title Versioned\n * @notice Version getter for contracts. Doesn't use any storage slots, meaning\n * it will never cause any troubles with the upgradeable contracts. For instance, this contract\n * can be added or removed from the inheritance chain without shifting the storage layout.\n */\nabstract contract Versioned {\n    /**\n     * @notice Struct that is mimicking the storage layout of a string with 32 bytes or less.\n     * Length is limited by 32, so the whole string payload takes two memory words:\n     * @param length    String length\n     * @param data      String characters\n     */\n    struct _ShortString {\n        uint256 length;\n        bytes32 data;\n    }\n\n    /// @dev Length of the \"version string\"\n    uint256 private immutable _length;\n    /// @dev Bytes representation of the \"version string\".\n    /// Strings with length over 32 are not supported!\n    bytes32 private immutable _data;\n\n    constructor(string memory version_) {\n        _length = bytes(version_).length;\n        if (_length \u003e 32) revert IncorrectVersionLength();\n        // bytes32 is left-aligned =\u003e this will store the byte representation of the string\n        // with the trailing zeroes to complete the 32-byte word\n        _data = bytes32(bytes(version_));\n    }\n\n    function version() external view returns (string memory versionString) {\n        // Load the immutable values to form the version string\n        _ShortString memory str = _ShortString(_length, _data);\n        // The only way to do this cast is doing some dirty assembly\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            versionString := str\n        }\n    }\n}\n\n// contracts/libs/ChainContext.sol\n\n/// @notice Library for accessing chain context variables as tightly packed integers.\n/// Messaging contracts should rely on this library for accessing chain context variables\n/// instead of doing the casting themselves.\nlibrary ChainContext {\n    using SafeCast for uint256;\n\n    /// @notice Returns the current block number as uint40.\n    /// @dev Reverts if block number is greater than 40 bits, which is not supposed to happen\n    /// until the block.timestamp overflows (assuming block time is at least 1 second).\n    function blockNumber() internal view returns (uint40) {\n        return block.number.toUint40();\n    }\n\n    /// @notice Returns the current block timestamp as uint40.\n    /// @dev Reverts if block timestamp is greater than 40 bits, which is\n    /// supposed to happen approximately in year 36835.\n    function blockTimestamp() internal view returns (uint40) {\n        return block.timestamp.toUint40();\n    }\n\n    /// @notice Returns the chain id as uint32.\n    /// @dev Reverts if chain id is greater than 32 bits, which is not\n    /// supposed to happen in production.\n    function chainId() internal view returns (uint32) {\n        return block.chainid.toUint32();\n    }\n}\n\n// contracts/libs/Structures.sol\n\n// Here we define common enums and structures to enable their easier reusing later.\n\n// ═══════════════════════════════ AGENT STATUS ════════════════════════════════\n\n/// @dev Potential statuses for the off-chain bonded agent:\n/// - Unknown: never provided a bond =\u003e signature not valid\n/// - Active: has a bond in BondingManager =\u003e signature valid\n/// - Unstaking: has a bond in BondingManager, initiated the unstaking =\u003e signature not valid\n/// - Resting: used to have a bond in BondingManager, successfully unstaked =\u003e signature not valid\n/// - Fraudulent: proven to commit fraud, value in Merkle Tree not updated =\u003e signature not valid\n/// - Slashed: proven to commit fraud, value in Merkle Tree was updated =\u003e signature not valid\n/// Unstaked agent could later be added back to THE SAME domain by staking a bond again.\n/// Honest agent: Unknown -\u003e Active -\u003e unstaking -\u003e Resting -\u003e Active ...\n/// Malicious agent: Unknown -\u003e Active -\u003e Fraudulent -\u003e Slashed\n/// Malicious agent: Unknown -\u003e Active -\u003e Unstaking -\u003e Fraudulent -\u003e Slashed\nenum AgentFlag {\n    Unknown,\n    Active,\n    Unstaking,\n    Resting,\n    Fraudulent,\n    Slashed\n}\n\n/// @notice Struct for storing an agent in the BondingManager contract.\nstruct AgentStatus {\n    AgentFlag flag;\n    uint32 domain;\n    uint32 index;\n}\n// 184 bits available for tight packing\n\nusing StructureUtils for AgentStatus global;\n\n/// @notice Potential statuses of an agent in terms of being in dispute\n/// - None: agent is not in dispute\n/// - Pending: agent is in unresolved dispute\n/// - Slashed: agent was in dispute that lead to agent being slashed\n/// Note: agent who won the dispute has their status reset to None\nenum DisputeFlag {\n    None,\n    Pending,\n    Slashed\n}\n\n/// @notice Struct for storing dispute status of an agent.\n/// @param flag         Dispute flag: None/Pending/Slashed.\n/// @param openedAt     Timestamp when the latest agent dispute was opened (zero if not opened).\n/// @param resolvedAt   Timestamp when the latest agent dispute was resolved (zero if not resolved).\nstruct DisputeStatus {\n    DisputeFlag flag;\n    uint40 openedAt;\n    uint40 resolvedAt;\n}\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\n/// @notice Struct representing the status of Destination contract.\n/// @param snapRootTime     Timestamp when latest snapshot root was accepted\n/// @param agentRootTime    Timestamp when latest agent root was accepted\n/// @param notaryIndex      Index of Notary who signed the latest agent root\nstruct DestinationStatus {\n    uint40 snapRootTime;\n    uint40 agentRootTime;\n    uint32 notaryIndex;\n}\n\n// ═══════════════════════════════ EXECUTION HUB ═══════════════════════════════\n\n/// @notice Potential statuses of the message in Execution Hub.\n/// - None: there hasn't been a valid attempt to execute the message yet\n/// - Failed: there was a valid attempt to execute the message, but recipient reverted\n/// - Success: there was a valid attempt to execute the message, and recipient did not revert\n/// Note: message can be executed until its status is Success\nenum MessageStatus {\n    None,\n    Failed,\n    Success\n}\n\nlibrary StructureUtils {\n    /// @notice Checks that Agent is Active\n    function verifyActive(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active) {\n            revert AgentNotActive();\n        }\n    }\n\n    /// @notice Checks that Agent is Unstaking\n    function verifyUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Unstaking) {\n            revert AgentNotUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Active or Unstaking\n    function verifyActiveUnstaking(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Active \u0026\u0026 status.flag != AgentFlag.Unstaking) {\n            revert AgentNotActiveNorUnstaking();\n        }\n    }\n\n    /// @notice Checks that Agent is Fraudulent\n    function verifyFraudulent(AgentStatus memory status) internal pure {\n        if (status.flag != AgentFlag.Fraudulent) {\n            revert AgentNotFraudulent();\n        }\n    }\n\n    /// @notice Checks that Agent is not Unknown\n    function verifyKnown(AgentStatus memory status) internal pure {\n        if (status.flag == AgentFlag.Unknown) {\n            revert AgentUnknown();\n        }\n    }\n}\n\n// contracts/libs/memory/MemView.sol\n\n/// @dev MemView is an untyped view over a portion of memory to be used instead of `bytes memory`\ntype MemView is uint256;\n\n/// @dev Attach library functions to MemView\nusing MemViewLib for MemView global;\n\n/// @notice Library for operations with the memory views.\n/// Forked from https://github.com/summa-tx/memview-sol with several breaking changes:\n/// - The codebase is ported to Solidity 0.8\n/// - Custom errors are added\n/// - The runtime type checking is replaced with compile-time check provided by User-Defined Value Types\n///   https://docs.soliditylang.org/en/latest/types.html#user-defined-value-types\n/// - uint256 is used as the underlying type for the \"memory view\" instead of bytes29.\n///   It is wrapped into MemView custom type in order not to be confused with actual integers.\n/// - Therefore the \"type\" field is discarded, allowing to allocate 16 bytes for both view location and length\n/// - The documentation is expanded\n/// - Library functions unused by the rest of the codebase are removed\n//  - Very pretty code separators are added :)\nlibrary MemViewLib {\n    /// @notice Stack layout for uint256 (from highest bits to lowest)\n    /// (32 .. 16]      loc     16 bytes    Memory address of underlying bytes\n    /// (16 .. 00]      len     16 bytes    Length of underlying bytes\n\n    // ═══════════════════════════════════════════ BUILDING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Instantiate a new untyped memory view. This should generally not be called directly.\n     * Prefer `ref` wherever possible.\n     * @param loc_          The memory address\n     * @param len_          The length\n     * @return The new view with the specified location and length\n     */\n    function build(uint256 loc_, uint256 len_) internal pure returns (MemView) {\n        uint256 end_ = loc_ + len_;\n        // Make sure that a view is not constructed that points to unallocated memory\n        // as this could be indicative of a buffer overflow attack\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            if gt(end_, mload(0x40)) { end_ := 0 }\n        }\n        if (end_ == 0) {\n            revert UnallocatedMemory();\n        }\n        return _unsafeBuildUnchecked(loc_, len_);\n    }\n\n    /**\n     * @notice Instantiate a memory view from a byte array.\n     * @dev Note that due to Solidity memory representation, it is not possible to\n     * implement a deref, as the `bytes` type stores its len in memory.\n     * @param arr           The byte array\n     * @return The memory view over the provided byte array\n     */\n    function ref(bytes memory arr) internal pure returns (MemView) {\n        uint256 len_ = arr.length;\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 loc_;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // We add 0x20, so that the view starts exactly where the array data starts\n            loc_ := add(arr, 0x20)\n        }\n        return build(loc_, len_);\n    }\n\n    // ════════════════════════════════════════════ CLONING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to the new memory.\n     * @param memView       The memory view\n     * @return arr          The cloned byte array\n     */\n    function clone(MemView memView) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        unchecked {\n            _unsafeCopyTo(memView, ptr + 0x20);\n        }\n        // `bytes arr` is stored in memory in the following way\n        // 1. First, uint256 arr.length is stored. That requires 32 bytes (0x20).\n        // 2. Then, the array data is stored.\n        uint256 len_ = memView.len();\n        uint256 footprint_ = memView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    /**\n     * @notice Copies all views, joins them into a new bytearray.\n     * @param memViews      The memory views\n     * @return arr          The new byte array with joined data behind the given views\n     */\n    function join(MemView[] memory memViews) internal view returns (bytes memory arr) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n            // This is where the byte array will be stored\n            arr := ptr\n        }\n        MemView newView;\n        unchecked {\n            newView = _unsafeJoin(memViews, ptr + 0x20);\n        }\n        uint256 len_ = newView.len();\n        uint256 footprint_ = newView.footprint();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Write new unused pointer: the old value + array footprint + 32 bytes to store the length\n            mstore(0x40, add(add(ptr, footprint_), 0x20))\n            // Write len of new array (in bytes)\n            mstore(ptr, len_)\n        }\n    }\n\n    // ══════════════════════════════════════════ INSPECTING MEMORY VIEW ═══════════════════════════════════════════════\n\n    /**\n     * @notice Returns the memory address of the underlying bytes.\n     * @param memView       The memory view\n     * @return loc_         The memory address\n     */\n    function loc(MemView memView) internal pure returns (uint256 loc_) {\n        // loc is stored in the highest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u003e\u003e 128;\n    }\n\n    /**\n     * @notice Returns the number of bytes of the view.\n     * @param memView       The memory view\n     * @return len_         The length of the view\n     */\n    function len(MemView memView) internal pure returns (uint256 len_) {\n        // len is stored in the lowest 16 bytes of the underlying uint256\n        return MemView.unwrap(memView) \u0026 type(uint128).max;\n    }\n\n    /**\n     * @notice Returns the endpoint of `memView`.\n     * @param memView       The memory view\n     * @return end_         The endpoint of `memView`\n     */\n    function end(MemView memView) internal pure returns (uint256 end_) {\n        // The endpoint never overflows uint128, let alone uint256, so we could use unchecked math here\n        unchecked {\n            return memView.loc() + memView.len();\n        }\n    }\n\n    /**\n     * @notice Returns the number of memory words this memory view occupies, rounded up.\n     * @param memView       The memory view\n     * @return words_       The number of memory words\n     */\n    function words(MemView memView) internal pure returns (uint256 words_) {\n        // returning ceil(length / 32.0)\n        unchecked {\n            return (memView.len() + 31) \u003e\u003e 5;\n        }\n    }\n\n    /**\n     * @notice Returns the in-memory footprint of a fresh copy of the view.\n     * @param memView       The memory view\n     * @return footprint_   The in-memory footprint of a fresh copy of the view.\n     */\n    function footprint(MemView memView) internal pure returns (uint256 footprint_) {\n        // words() * 32\n        return memView.words() \u003c\u003c 5;\n    }\n\n    // ════════════════════════════════════════════ HASHING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the keccak256 hash of the underlying memory\n     * @param memView       The memory view\n     * @return digest       The keccak256 hash of the underlying memory\n     */\n    function keccak(MemView memView) internal pure returns (bytes32 digest) {\n        uint256 loc_ = memView.loc();\n        uint256 len_ = memView.len();\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            digest := keccak256(loc_, len_)\n        }\n    }\n\n    /**\n     * @notice Adds a salt to the keccak256 hash of the underlying data and returns the keccak256 hash of the\n     * resulting data.\n     * @param memView       The memory view\n     * @return digestSalted keccak256(salt, keccak256(memView))\n     */\n    function keccakSalted(MemView memView, bytes32 salt) internal pure returns (bytes32 digestSalted) {\n        return keccak256(bytes.concat(salt, memView.keccak()));\n    }\n\n    // ════════════════════════════════════════════ SLICING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Safe slicing without memory modification.\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the given index\n     */\n    function slice(MemView memView, uint256 index_, uint256 len_) internal pure returns (MemView) {\n        uint256 loc_ = memView.loc();\n        // Ensure it doesn't overrun the view\n        if (loc_ + index_ + len_ \u003e memView.end()) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // loc_ + index_ \u003c= memView.end()\n            return build({loc_: loc_ + index_, len_: len_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing bytes from `index` to end(memView).\n     * @param memView       The memory view\n     * @param index_        The start index\n     * @return The new view for the slice starting from the given index until the initial view endpoint\n     */\n    function sliceFrom(MemView memView, uint256 index_) internal pure returns (MemView) {\n        uint256 len_ = memView.len();\n        // Ensure it doesn't overrun the view\n        if (index_ \u003e len_) {\n            revert ViewOverrun();\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // index_ \u003c= len_ =\u003e memView.loc() + index_ \u003c= memView.loc() + memView.len() == memView.end()\n            return build({loc_: memView.loc() + index_, len_: len_ - index_});\n        }\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the first `len` bytes.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length starting from the initial view beginning\n     */\n    function prefix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        return memView.slice({index_: 0, len_: len_});\n    }\n\n    /**\n     * @notice Shortcut to `slice`. Gets a view representing the last `len` byte.\n     * @param memView       The memory view\n     * @param len_          The length\n     * @return The new view for the slice of the given length until the initial view endpoint\n     */\n    function postfix(MemView memView, uint256 len_) internal pure returns (MemView) {\n        uint256 viewLen = memView.len();\n        // Ensure it doesn't overrun the view\n        if (len_ \u003e viewLen) {\n            revert ViewOverrun();\n        }\n        // Could do the unchecked math due to the check above\n        uint256 index_;\n        unchecked {\n            index_ = viewLen - len_;\n        }\n        // Build a view starting from index with the given length\n        unchecked {\n            // len_ \u003c= memView.len() =\u003e memView.loc() \u003c= loc_ \u003c= memView.end()\n            return build({loc_: memView.loc() + viewLen - len_, len_: len_});\n        }\n    }\n\n    // ═══════════════════════════════════════════ INDEXING MEMORY VIEW ════════════════════════════════════════════════\n\n    /**\n     * @notice Load up to 32 bytes from the view onto the stack.\n     * @dev Returns a bytes32 with only the `bytes_` HIGHEST bytes set.\n     * This can be immediately cast to a smaller fixed-length byte array.\n     * To automatically cast to an integer, use `indexUint`.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return result       The 32 byte result having only `bytes_` highest bytes set\n     */\n    function index(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (bytes32 result) {\n        if (bytes_ == 0) {\n            return bytes32(0);\n        }\n        // Can't load more than 32 bytes to the stack in one go\n        if (bytes_ \u003e 32) {\n            revert IndexedTooMuch();\n        }\n        // The last indexed byte should be within view boundaries\n        if (index_ + bytes_ \u003e memView.len()) {\n            revert ViewOverrun();\n        }\n        uint256 bitLength = bytes_ \u003c\u003c 3; // bytes_ * 8\n        uint256 loc_ = memView.loc();\n        // Get a mask with `bitLength` highest bits set\n        uint256 mask;\n        // 0x800...00 binary representation is 100...00\n        // sar stands for \"signed arithmetic shift\": https://en.wikipedia.org/wiki/Arithmetic_shift\n        // sar(N-1, 100...00) = 11...100..00, with exactly N highest bits set to 1\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            mask := sar(sub(bitLength, 1), 0x8000000000000000000000000000000000000000000000000000000000000000)\n        }\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load a full word using index offset, and apply mask to ignore non-relevant bytes\n            result := and(mload(add(loc_, index_)), mask)\n        }\n    }\n\n    /**\n     * @notice Parse an unsigned integer from the view at `index`.\n     * @dev Requires that the view have \u003e= `bytes_` bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @param bytes_        The amount of bytes to load onto the stack\n     * @return The unsigned integer\n     */\n    function indexUint(MemView memView, uint256 index_, uint256 bytes_) internal pure returns (uint256) {\n        bytes32 indexedBytes = memView.index(index_, bytes_);\n        // `index()` returns left-aligned `bytes_`, while integers are right-aligned\n        // Shifting here to right-align with the full 32 bytes word: need to shift right `(32 - bytes_)` bytes\n        unchecked {\n            // memView.index() reverts when bytes_ \u003e 32, thus unchecked math\n            return uint256(indexedBytes) \u003e\u003e ((32 - bytes_) \u003c\u003c 3);\n        }\n    }\n\n    /**\n     * @notice Parse an address from the view at `index`.\n     * @dev Requires that the view have \u003e= 20 bytes following that index.\n     * @param memView       The memory view\n     * @param index_        The index\n     * @return The address\n     */\n    function indexAddress(MemView memView, uint256 index_) internal pure returns (address) {\n        // index 20 bytes as `uint160`, and then cast to `address`\n        return address(uint160(memView.indexUint(index_, 20)));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns a memory view over the specified memory location\n    /// without checking if it points to unallocated memory.\n    function _unsafeBuildUnchecked(uint256 loc_, uint256 len_) private pure returns (MemView) {\n        // There is no scenario where loc or len would overflow uint128, so we omit this check.\n        // We use the highest 128 bits to encode the location and the lowest 128 bits to encode the length.\n        return MemView.wrap((loc_ \u003c\u003c 128) | len_);\n    }\n\n    /**\n     * @notice Copy the view to a location, return an unsafe memory reference\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memView       The memory view\n     * @param newLoc        The new location to copy the underlying view data\n     * @return The memory view over the unsafe memory with the copied underlying data\n     */\n    function _unsafeCopyTo(MemView memView, uint256 newLoc) private view returns (MemView) {\n        uint256 len_ = memView.len();\n        uint256 oldLoc = memView.loc();\n\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (newLoc \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        bool res;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // use the identity precompile (0x04) to copy\n            res := staticcall(gas(), 0x04, oldLoc, len_, newLoc, len_)\n        }\n        if (!res) revert PrecompileOutOfGas();\n        return _unsafeBuildUnchecked({loc_: newLoc, len_: len_});\n    }\n\n    /**\n     * @notice Join the views in memory, return an unsafe reference to the memory.\n     * @dev Super Dangerous direct memory access.\n     * This reference can be overwritten if anything else modifies memory (!!!).\n     * As such it MUST be consumed IMMEDIATELY. Update the free memory pointer to ensure the copied data\n     * is not overwritten. This function is private to prevent unsafe usage by callers.\n     * @param memViews      The memory views\n     * @return The conjoined view pointing to the new memory\n     */\n    function _unsafeJoin(MemView[] memory memViews, uint256 location) private view returns (MemView) {\n        uint256 ptr;\n        assembly {\n            // solhint-disable-previous-line no-inline-assembly\n            // Load unused memory pointer\n            ptr := mload(0x40)\n        }\n        // Revert if we're writing in occupied memory\n        if (location \u003c ptr) {\n            revert OccupiedMemory();\n        }\n        // Copy the views to the specified location one by one, by tracking the amount of copied bytes so far\n        uint256 offset = 0;\n        for (uint256 i = 0; i \u003c memViews.length;) {\n            MemView memView = memViews[i];\n            // We can use the unchecked math here as location + sum(view.length) will never overflow uint256\n            unchecked {\n                _unsafeCopyTo(memView, location + offset);\n                offset += memView.len();\n                ++i;\n            }\n        }\n        return _unsafeBuildUnchecked({loc_: location, len_: offset});\n    }\n}\n\n// contracts/libs/merkle/MerkleMath.sol\n\nlibrary MerkleMath {\n    // ═════════════════════════════════════════ BASIC MERKLE CALCULATIONS ═════════════════════════════════════════════\n\n    /**\n     * @notice Calculates the merkle root for the given leaf and merkle proof.\n     * @dev Will revert if proof length exceeds the tree height.\n     * @param index     Index of `leaf` in tree\n     * @param leaf      Leaf of the merkle tree\n     * @param proof     Proof of inclusion of `leaf` in the tree\n     * @param height    Height of the merkle tree\n     * @return root_    Calculated Merkle Root\n     */\n    function proofRoot(uint256 index, bytes32 leaf, bytes32[] memory proof, uint256 height)\n        internal\n        pure\n        returns (bytes32 root_)\n    {\n        // Proof length could not exceed the tree height\n        uint256 proofLen = proof.length;\n        if (proofLen \u003e height) revert TreeHeightTooLow();\n        root_ = leaf;\n        /// @dev Apply unchecked to all ++h operations\n        unchecked {\n            // Go up the tree levels from the leaf following the proof\n            for (uint256 h = 0; h \u003c proofLen; ++h) {\n                // Get a sibling node on current level: this is proof[h]\n                root_ = getParent(root_, proof[h], index, h);\n            }\n            // Go up to the root: the remaining siblings are EMPTY\n            for (uint256 h = proofLen; h \u003c height; ++h) {\n                root_ = getParent(root_, bytes32(0), index, h);\n            }\n        }\n    }\n\n    /**\n     * @notice Calculates the parent of a node on the path from one of the leafs to root.\n     * @param node          Node on a path from tree leaf to root\n     * @param sibling       Sibling for a given node\n     * @param leafIndex     Index of the tree leaf\n     * @param nodeHeight    \"Level height\" for `node` (ZERO for leafs, ORIGIN_TREE_HEIGHT for root)\n     */\n    function getParent(bytes32 node, bytes32 sibling, uint256 leafIndex, uint256 nodeHeight)\n        internal\n        pure\n        returns (bytes32 parent)\n    {\n        // Index for `node` on its \"tree level\" is (leafIndex / 2**height)\n        // \"Left child\" has even index, \"right child\" has odd index\n        if ((leafIndex \u003e\u003e nodeHeight) \u0026 1 == 0) {\n            // Left child\n            return getParent(node, sibling);\n        } else {\n            // Right child\n            return getParent(sibling, node);\n        }\n    }\n\n    /// @notice Calculates the parent of tow nodes in the merkle tree.\n    /// @dev We use implementation with H(0,0) = 0\n    /// This makes EVERY empty node in the tree equal to ZERO,\n    /// saving us from storing H(0,0), H(H(0,0), H(0, 0)), and so on\n    /// @param leftChild    Left child of the calculated node\n    /// @param rightChild   Right child of the calculated node\n    /// @return parent      Value for the node having above mentioned children\n    function getParent(bytes32 leftChild, bytes32 rightChild) internal pure returns (bytes32 parent) {\n        if (leftChild == bytes32(0) \u0026\u0026 rightChild == bytes32(0)) {\n            return 0;\n        } else {\n            return keccak256(bytes.concat(leftChild, rightChild));\n        }\n    }\n\n    // ════════════════════════════════ ROOT/PROOF CALCULATION FOR A LIST OF LEAFS ═════════════════════════════════════\n\n    /**\n     * @notice Calculates merkle root for a list of given leafs.\n     * Merkle Tree is constructed by padding the list with ZERO values for leafs until list length is `2**height`.\n     * Merkle Root is calculated for the constructed tree, and then saved in `leafs[0]`.\n     * \u003e Note:\n     * \u003e - `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * \u003e - Caller is expected not to reuse `hashes` list after the call, and only use `leafs[0]` value,\n     * which is guaranteed to contain the calculated merkle root.\n     * \u003e - root is calculated using the `H(0,0) = 0` Merkle Tree implementation. See MerkleTree.sol for details.\n     * @dev Amount of leaves should be at most `2**height`\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param height    Height of the Merkle Tree to construct\n     */\n    function calculateRoot(bytes32[] memory hashes, uint256 height) internal pure {\n        uint256 levelLength = hashes.length;\n        // Amount of hashes could not exceed amount of leafs in tree with the given height\n        if (levelLength \u003e (1 \u003c\u003c height)) revert TreeHeightTooLow();\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\": the amount of iterations for the for loop above.\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n            }\n        }\n    }\n\n    /**\n     * @notice Generates a proof of inclusion of a leaf in the list. If the requested index is outside\n     * of the list range, generates a proof of inclusion for an empty leaf (proof of non-inclusion).\n     * The Merkle Tree is constructed by padding the list with ZERO values until list length is a power of two\n     * __AND__ index is in the extended list range. For example:\n     *  - `hashes.length == 6` and `0 \u003c= index \u003c= 7` will \"extend\" the list to 8 entries.\n     *  - `hashes.length == 6` and `7 \u003c index \u003c= 15` will \"extend\" the list to 16 entries.\n     * \u003e Note: `leafs` values are overwritten in the process to avoid excessive memory allocations.\n     * Caller is expected not to reuse `hashes` list after the call.\n     * @param hashes    List of leafs for the merkle tree (to be overwritten)\n     * @param index     Leaf index to generate the proof for\n     * @return proof    Generated merkle proof\n     */\n    function calculateProof(bytes32[] memory hashes, uint256 index) internal pure returns (bytes32[] memory proof) {\n        // Use only meaningful values for the shortened proof\n        // Check if index is within the list range (we want to generates proofs for outside leafs as well)\n        uint256 height = getHeight(index \u003c hashes.length ? hashes.length : (index + 1));\n        proof = new bytes32[](height);\n        uint256 levelLength = hashes.length;\n        /// @dev h, leftIndex, rightIndex and levelLength never overflow\n        unchecked {\n            // Iterate `height` levels up from the leaf level\n            // For every level we will only record \"significant values\", i.e. not equal to ZERO\n            for (uint256 h = 0; h \u003c height; ++h) {\n                // Use sibling for the merkle proof; `index^1` is index of our sibling\n                proof[h] = (index ^ 1 \u003c levelLength) ? hashes[index ^ 1] : bytes32(0);\n\n                // Let H be the height of the \"current level\". H = 0 for the \"leafs level\".\n                // Invariant: a total of 2**(HEIGHT-H) nodes are on the current level\n                // Invariant: hashes[0 .. length) are \"significant values\" for the \"current level\" nodes\n                // Invariant: bytes32(0) is the value for nodes with indexes [length .. 2**(HEIGHT-H))\n\n                // Iterate over every pair of (leftChild, rightChild) on the current level\n                for (uint256 leftIndex = 0; leftIndex \u003c levelLength; leftIndex += 2) {\n                    uint256 rightIndex = leftIndex + 1;\n                    bytes32 leftChild = hashes[leftIndex];\n                    // Note: rightChild might be ZERO\n                    bytes32 rightChild = rightIndex \u003c levelLength ? hashes[rightIndex] : bytes32(0);\n                    // Record the parent hash in the same array. This will not affect\n                    // further calculations for the same level: (leftIndex \u003e\u003e 1) \u003c= leftIndex.\n                    hashes[leftIndex \u003e\u003e 1] = getParent(leftChild, rightChild);\n                }\n                // Set length for the \"parent level\"\n                levelLength = (levelLength + 1) \u003e\u003e 1;\n                // Traverse to parent node\n                index \u003e\u003e= 1;\n            }\n        }\n    }\n\n    /// @notice Returns the height of the tree having a given amount of leafs.\n    function getHeight(uint256 leafs) internal pure returns (uint256 height) {\n        uint256 amount = 1;\n        while (amount \u003c leafs) {\n            unchecked {\n                ++height;\n            }\n            amount \u003c\u003c= 1;\n        }\n    }\n}\n\n// contracts/libs/stack/GasData.sol\n\n/// GasData in encoded data with \"basic information about gas prices\" for some chain.\ntype GasData is uint96;\n\nusing GasDataLib for GasData global;\n\n/// ChainGas is encoded data with given chain's \"basic information about gas prices\".\ntype ChainGas is uint128;\n\nusing GasDataLib for ChainGas global;\n\n/// Library for encoding and decoding GasData and ChainGas structs.\n/// # GasData\n/// `GasData` is a struct to store the \"basic information about gas prices\", that could\n/// be later used to approximate the cost of a message execution, and thus derive the\n/// minimal tip values for sending a message to the chain.\n/// \u003e - `GasData` is supposed to be cached by `GasOracle` contract, allowing to store the\n/// \u003e approximates instead of the exact values, and thus save on storage costs.\n/// \u003e - For instance, if `GasOracle` only updates the values on +- 10% change, having an\n/// \u003e 0.4% error on the approximates would be acceptable.\n/// `GasData` is supposed to be included in the Origin's state, which are synced across\n/// chains using Agent-signed snapshots and attestations.\n/// ## GasData stack layout (from highest bits to lowest)\n///\n/// | Position   | Field        | Type   | Bytes | Description                                         |\n/// | ---------- | ------------ | ------ | ----- | --------------------------------------------------- |\n/// | (012..010] | gasPrice     | uint16 | 2     | Gas price for the chain (in Wei per gas unit)       |\n/// | (010..008] | dataPrice    | uint16 | 2     | Calldata price (in Wei per byte of content)         |\n/// | (008..006] | execBuffer   | uint16 | 2     | Tx fee safety buffer for message execution (in Wei) |\n/// | (006..004] | amortAttCost | uint16 | 2     | Amortized cost for attestation submission (in Wei)  |\n/// | (004..002] | etherPrice   | uint16 | 2     | Chain's Ether Price / Mainnet Ether Price (in BWAD) |\n/// | (002..000] | markup       | uint16 | 2     | Markup for the message execution (in BWAD)          |\n/// \u003e See Number.sol for more details on `Number` type and BWAD (binary WAD) math.\n///\n/// ## ChainGas stack layout (from highest bits to lowest)\n///\n/// | Position   | Field   | Type   | Bytes | Description      |\n/// | ---------- | ------- | ------ | ----- | ---------------- |\n/// | (016..004] | gasData | uint96 | 12    | Chain's gas data |\n/// | (004..000] | domain  | uint32 | 4     | Chain's domain   |\nlibrary GasDataLib {\n    /// @dev Amount of bits to shift to gasPrice field\n    uint96 private constant SHIFT_GAS_PRICE = 10 * 8;\n    /// @dev Amount of bits to shift to dataPrice field\n    uint96 private constant SHIFT_DATA_PRICE = 8 * 8;\n    /// @dev Amount of bits to shift to execBuffer field\n    uint96 private constant SHIFT_EXEC_BUFFER = 6 * 8;\n    /// @dev Amount of bits to shift to amortAttCost field\n    uint96 private constant SHIFT_AMORT_ATT_COST = 4 * 8;\n    /// @dev Amount of bits to shift to etherPrice field\n    uint96 private constant SHIFT_ETHER_PRICE = 2 * 8;\n\n    /// @dev Amount of bits to shift to gasData field\n    uint128 private constant SHIFT_GAS_DATA = 4 * 8;\n\n    // ═════════════════════════════════════════════════ GAS DATA ══════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded GasData struct with the given fields.\n    /// @param gasPrice_        Gas price for the chain (in Wei per gas unit)\n    /// @param dataPrice_       Calldata price (in Wei per byte of content)\n    /// @param execBuffer_      Tx fee safety buffer for message execution (in Wei)\n    /// @param amortAttCost_    Amortized cost for attestation submission (in Wei)\n    /// @param etherPrice_      Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n    /// @param markup_          Markup for the message execution (in BWAD)\n    function encodeGasData(\n        Number gasPrice_,\n        Number dataPrice_,\n        Number execBuffer_,\n        Number amortAttCost_,\n        Number etherPrice_,\n        Number markup_\n    ) internal pure returns (GasData) {\n        // Number type wraps uint16, so could safely be casted to uint96\n        // forgefmt: disable-next-item\n        return GasData.wrap(\n            uint96(Number.unwrap(gasPrice_)) \u003c\u003c SHIFT_GAS_PRICE |\n            uint96(Number.unwrap(dataPrice_)) \u003c\u003c SHIFT_DATA_PRICE |\n            uint96(Number.unwrap(execBuffer_)) \u003c\u003c SHIFT_EXEC_BUFFER |\n            uint96(Number.unwrap(amortAttCost_)) \u003c\u003c SHIFT_AMORT_ATT_COST |\n            uint96(Number.unwrap(etherPrice_)) \u003c\u003c SHIFT_ETHER_PRICE |\n            uint96(Number.unwrap(markup_))\n        );\n    }\n\n    /// @notice Wraps padded uint256 value into GasData struct.\n    function wrapGasData(uint256 paddedGasData) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(paddedGasData));\n    }\n\n    /// @notice Returns the gas price, in Wei per gas unit.\n    function gasPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_GAS_PRICE));\n    }\n\n    /// @notice Returns the calldata price, in Wei per byte of content.\n    function dataPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_DATA_PRICE));\n    }\n\n    /// @notice Returns the tx fee safety buffer for message execution, in Wei.\n    function execBuffer(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_EXEC_BUFFER));\n    }\n\n    /// @notice Returns the amortized cost for attestation submission, in Wei.\n    function amortAttCost(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_AMORT_ATT_COST));\n    }\n\n    /// @notice Returns the ratio of Chain's Ether Price / Mainnet Ether Price, in BWAD math.\n    function etherPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_ETHER_PRICE));\n    }\n\n    /// @notice Returns the markup for the message execution, in BWAD math.\n    function markup(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data)));\n    }\n\n    // ════════════════════════════════════════════════ CHAIN DATA ═════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded ChainGas struct with the given fields.\n    /// @param gasData_ Chain's gas data\n    /// @param domain_  Chain's domain\n    function encodeChainGas(GasData gasData_, uint32 domain_) internal pure returns (ChainGas) {\n        // GasData type wraps uint96, so could safely be casted to uint128\n        return ChainGas.wrap(uint128(GasData.unwrap(gasData_)) \u003c\u003c SHIFT_GAS_DATA | uint128(domain_));\n    }\n\n    /// @notice Wraps padded uint256 value into ChainGas struct.\n    function wrapChainGas(uint256 paddedChainGas) internal pure returns (ChainGas) {\n        // Casting to uint128 will truncate the highest bits, which is the behavior we want\n        return ChainGas.wrap(uint128(paddedChainGas));\n    }\n\n    /// @notice Returns the chain's gas data.\n    function gasData(ChainGas data) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(ChainGas.unwrap(data) \u003e\u003e SHIFT_GAS_DATA));\n    }\n\n    /// @notice Returns the chain's domain.\n    function domain(ChainGas data) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(ChainGas.unwrap(data));\n    }\n\n    /// @notice Returns the hash for the list of ChainGas structs.\n    function snapGasHash(ChainGas[] memory snapGas) internal pure returns (bytes32 snapGasHash_) {\n        // Use assembly to calculate the hash of the array without copying it\n        // ChainGas takes a single word of storage, thus ChainGas[] is stored in the following way:\n        // 0x00: length of the array, in words\n        // 0x20: first ChainGas struct\n        // 0x40: second ChainGas struct\n        // And so on...\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Find the location where the array data starts, we add 0x20 to skip the length field\n            let loc := add(snapGas, 0x20)\n            // Load the length of the array (in words).\n            // Shifting left 5 bits is equivalent to multiplying by 32: this converts from words to bytes.\n            let len := shl(5, mload(snapGas))\n            // Calculate the hash of the array\n            snapGasHash_ := keccak256(loc, len)\n        }\n    }\n}\n\n// contracts/libs/stack/Header.sol\n\n/// Header is encoded data with \"general routing information\".\ntype Header is uint136;\n\nusing HeaderLib for Header global;\n\n/// Types of messages supported by Origin-Destination\n/// - Base: message sent by protocol user, contains tips\n/// - Manager: message sent between AgentManager contracts located on different chains, no tips\nenum MessageFlag {\n    Base,\n    Manager\n}\n\nusing HeaderLib for MessageFlag global;\n\n/// Library for formatting _the header part_ of _the messages used by Origin and Destination_.\n/// - Header represents general information for routing a Message for Origin and Destination.\n/// - Header occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n///\n/// # Header stack layout (from highest bits to lowest)\n///\n/// | Position   | Field            | Type   | Bytes | Description                             |\n/// | ---------- | ---------------- | ------ | ----- | --------------------------------------- |\n/// | (017..016] | flag             | uint8  | 1     | Flag specifying the type of message     |\n/// | (016..012] | origin           | uint32 | 4     | Domain where message originated         |\n/// | (012..008] | nonce            | uint32 | 4     | Message nonce on the origin domain      |\n/// | (008..004] | destination      | uint32 | 4     | Domain where message will be executed   |\n/// | (004..000] | optimisticPeriod | uint32 | 4     | Optimistic period that will be enforced |\nlibrary HeaderLib {\n    /// @dev Amount of bits to shift to flag field\n    uint136 private constant SHIFT_FLAG = 16 * 8;\n    /// @dev Amount of bits to shift to origin field\n    uint136 private constant SHIFT_ORIGIN = 12 * 8;\n    /// @dev Amount of bits to shift to nonce field\n    uint136 private constant SHIFT_NONCE = 8 * 8;\n    /// @dev Amount of bits to shift to destination field\n    uint136 private constant SHIFT_DESTINATION = 4 * 8;\n\n    /// @notice Returns an encoded header with provided fields\n    /// @param origin_              Domain of origin chain\n    /// @param nonce_               Message nonce on origin chain\n    /// @param destination_         Domain of destination chain\n    /// @param optimisticPeriod_    Optimistic period for message execution\n    function encodeHeader(\n        MessageFlag flag_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint32 destination_,\n        uint32 optimisticPeriod_\n    ) internal pure returns (Header) {\n        // All casts below are upcasts, so they are safe\n        // forgefmt: disable-next-item\n        return Header.wrap(\n            uint136(uint8(flag_)) \u003c\u003c SHIFT_FLAG |\n            uint136(origin_) \u003c\u003c SHIFT_ORIGIN |\n            uint136(nonce_) \u003c\u003c SHIFT_NONCE |\n            uint136(destination_) \u003c\u003c SHIFT_DESTINATION |\n            uint136(optimisticPeriod_)\n        );\n    }\n\n    /// @notice Checks that the header is a valid encoded header.\n    function isHeader(uint256 paddedHeader) internal pure returns (bool) {\n        // Check that flag is within range\n        return _flag(paddedHeader) \u003c= uint8(type(MessageFlag).max);\n    }\n\n    /// @notice Wraps the padded encoded request into a Header-typed value.\n    /// @dev The \"padded\" header is simply an encoded header casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded headers\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedHeader) internal pure returns (Header) {\n        // Check that flag is within range\n        if (!isHeader(paddedHeader)) revert FlagOutOfRange();\n        // Casting to uint136 will truncate the highest bits, which is the behavior we want\n        return Header.wrap(uint136(paddedHeader));\n    }\n\n    /// @notice Returns header's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Header header) internal pure returns (bytes32 hashedHeader) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store header in scratch space\n            mstore(0, header)\n            // Compute hash of header padded to 32 bytes\n            hashedHeader := keccak256(0, 32)\n        }\n    }\n\n    // ══════════════════════════════════════════════ HEADER SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns header's flag field\n    function flag(Header header) internal pure returns (MessageFlag) {\n        // We check that flag is within range when wrapping the header, so this cast is safe\n        return MessageFlag(_flag(Header.unwrap(header)));\n    }\n\n    /// @notice Returns header's origin field\n    function origin(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_ORIGIN);\n    }\n\n    /// @notice Returns header's nonce field\n    function nonce(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_NONCE);\n    }\n\n    /// @notice Returns header's destination field\n    function destination(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header) \u003e\u003e SHIFT_DESTINATION);\n    }\n\n    /// @notice Returns header's optimistic seconds field\n    function optimisticPeriod(Header header) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Header.unwrap(header));\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns header's flag field without casting to MessageFlag\n    function _flag(uint256 paddedHeader) private pure returns (uint8) {\n        // Casting to uint8 will truncate the highest bits, which is the behavior we want\n        return uint8(paddedHeader \u003e\u003e SHIFT_FLAG);\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n     * constructor.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall \u0026\u0026 _initialized \u003c 1) || (!AddressUpgradeable.isContract(address(this)) \u0026\u0026 _initialized == 1),\n            \"Initializable: contract is already initialized\"\n        );\n        _initialized = 1;\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: setting the version to 255 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing \u0026\u0026 _initialized \u003c version, \"Initializable: contract is already initialized\");\n        _initialized = version;\n        _initializing = true;\n        _;\n        _initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        require(_initializing, \"Initializable: contract is not initializing\");\n        _;\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized != type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint8) {\n        return _initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _initializing;\n    }\n}\n\n// contracts/interfaces/IAgentManager.sol\n\ninterface IAgentManager {\n    /**\n     * @notice Allows Inbox to open a Dispute between a Guard and a Notary, if they are both not in Dispute already.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Guard or Notary is already in Dispute.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Allows Inbox to slash an agent, if their fraud was proven.\n     * \u003e Will revert if any of these is true:\n     * \u003e - Caller is not Inbox.\n     * \u003e - Domain doesn't match the saved agent domain.\n     * @param domain    Domain where the Agent is active\n     * @param agent     Address of the Agent\n     * @param prover    Address that initially provided fraud proof\n     */\n    function slashAgent(uint32 domain, address agent, address prover) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the latest known root of the Agent Merkle Tree.\n     */\n    function agentRoot() external view returns (bytes32);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns the number of opened Disputes.\n     * @dev This includes the Disputes that have been resolved already.\n     */\n    function getDisputesAmount() external view returns (uint256);\n\n    /**\n     * @notice Returns information about the dispute with the given index.\n     * @dev Will revert if dispute with given index hasn't been opened yet.\n     * @param index             Dispute index\n     * @return guard            Address of the Guard in the Dispute\n     * @return notary           Address of the Notary in the Dispute\n     * @return slashedAgent     Address of the Agent who was slashed when Dispute was resolved\n     * @return fraudProver      Address who provided fraud proof to resolve the Dispute\n     * @return reportPayload    Raw payload with report data that led to the Dispute\n     * @return reportSignature  Guard signature for the report payload\n     */\n    function getDispute(uint256 index)\n        external\n        view\n        returns (\n            address guard,\n            address notary,\n            address slashedAgent,\n            address fraudProver,\n            bytes memory reportPayload,\n            bytes memory reportSignature\n        );\n\n    /**\n     * @notice Returns the current Dispute status of a given agent. See Structures.sol for details.\n     * @dev Every returned value will be set to zero if agent was not slashed and is not in Dispute.\n     * `rival` and `disputePtr` will be set to zero if the agent was slashed without being in Dispute.\n     * @param agent         Agent address\n     * @return flag         Flag describing the current Dispute status for the agent: None/Pending/Slashed\n     * @return rival        Address of the rival agent in the Dispute\n     * @return fraudProver  Address who provided fraud proof to resolve the Dispute\n     * @return disputePtr   Index of the opened Dispute PLUS ONE. Zero if agent is not in Dispute.\n     */\n    function disputeStatus(address agent)\n        external\n        view\n        returns (DisputeFlag flag, address rival, address fraudProver, uint256 disputePtr);\n}\n\n// contracts/interfaces/IAgentSecured.sol\n\ninterface IAgentSecured {\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * between a Guard and a Notary has been opened.\n     * @param guardIndex    Index of the Guard in the Agent Merkle Tree\n     * @param notaryIndex   Index of the Notary in the Agent Merkle Tree\n     */\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external;\n\n    /**\n     * @notice Local AgentManager should call this function to indicate that a dispute\n     * has been resolved due to one of the agents being slashed.\n     * \u003e `rivalIndex` will be ZERO, if the slashed agent was not in the Dispute.\n     * @param slashedIndex  Index of the slashed agent in the Agent Merkle Tree\n     * @param rivalIndex    Index of the their Dispute Rival in the Agent Merkle Tree\n     */\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the address of the local AgentManager contract, which is treated as\n     * the \"source of truth\" for agent statuses.\n     */\n    function agentManager() external view returns (address);\n\n    /**\n     * @notice Returns the address of the local Inbox contract, which is treated as\n     * the \"source of truth\" for agent-signed statements.\n     * @dev Inbox passes verified agent statements to `IAgentSecured` contract.\n     */\n    function inbox() external view returns (address);\n\n    /**\n     * @notice Returns (flag, domain, index) for a given agent. See Structures.sol for details.\n     * @dev Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud,\n     * but their status is not updated to Slashed yet.\n     * @param agent     Agent address\n     * @return          Status for the given agent: (flag, domain, index).\n     */\n    function agentStatus(address agent) external view returns (AgentStatus memory);\n\n    /**\n     * @notice Returns agent address and their current status for a given agent index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param index     Agent index in the Agent Merkle Tree\n     * @return agent    Agent address\n     * @return status   Status for the given agent: (flag, domain, index)\n     */\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status);\n\n    /**\n     * @notice Returns (flag, openedAt, resolvedAt) that describes the latest status of\n     * the latest dispute for an agent with a given index.\n     * @dev Will return empty values if agent with given index doesn't exist.\n     * @param agentIndex    Agent index in the Agent Merkle Tree\n     * @return              Latest dispute status for the given agent: (flag, openedAt, resolvedAt)\n     */\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory);\n}\n\n// contracts/libs/memory/ByteString.sol\n\n/// @dev CallData is a memory view over the payload to be used for an external call, i.e.\n/// recipient.call(callData). Its length is always (4 + 32 * N) bytes:\n/// - First 4 bytes represent the function selector.\n/// - 32 * N bytes represent N words that function arguments occupy.\ntype CallData is uint256;\n\n/// @dev Attach library functions to CallData\nusing ByteString for CallData global;\n\n/// @dev Signature is a memory view over a \"65 bytes\" array representing a ECDSA signature.\ntype Signature is uint256;\n\n/// @dev Attach library functions to Signature\nusing ByteString for Signature global;\n\nlibrary ByteString {\n    using MemViewLib for bytes;\n\n    /**\n     * @dev non-compact ECDSA signatures are enforced as of OZ 4.7.3\n     *\n     *      Signature payload memory layout\n     * [000 .. 032) r   bytes32 32 bytes\n     * [032 .. 064) s   bytes32 32 bytes\n     * [064 .. 065) v   uint8    1 byte\n     */\n    uint256 internal constant SIGNATURE_LENGTH = 65;\n    uint256 private constant OFFSET_R = 0;\n    uint256 private constant OFFSET_S = 32;\n    uint256 private constant OFFSET_V = 64;\n\n    /**\n     * @dev Calldata memory layout\n     * [000 .. 004) selector    bytes4  4 bytes\n     *      Optional: N function arguments\n     * [004 .. 036) arg1        bytes32 32 bytes\n     *      ..\n     * [AAA .. END) argN        bytes32 32 bytes\n     */\n    uint256 internal constant SELECTOR_LENGTH = 4;\n    uint256 private constant OFFSET_SELECTOR = 0;\n    uint256 private constant OFFSET_ARGUMENTS = SELECTOR_LENGTH;\n\n    // ═════════════════════════════════════════════════ SIGNATURE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the signature payload from the given values.\n     * @dev Using ByteString.formatSignature({r: r, s: s, v: v}) will make sure\n     * that params are given in the right order.\n     */\n    function formatSignature(bytes32 r, bytes32 s, uint8 v) internal pure returns (bytes memory) {\n        return abi.encodePacked(r, s, v);\n    }\n\n    /**\n     * @notice Returns a Signature view over for the given payload.\n     * @dev Will revert if the payload is not a signature.\n     */\n    function castToSignature(bytes memory payload) internal pure returns (Signature) {\n        return castToSignature(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Signature view.\n     * @dev Will revert if the memory view is not over a signature.\n     */\n    function castToSignature(MemView memView) internal pure returns (Signature) {\n        if (!isSignature(memView)) revert UnformattedSignature();\n        return Signature.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a signature\n     */\n    function isSignature(MemView memView) internal pure returns (bool) {\n        return memView.len() == SIGNATURE_LENGTH;\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Signature signature) internal pure returns (MemView) {\n        return MemView.wrap(Signature.unwrap(signature));\n    }\n\n    // ═════════════════════════════════════════════ SIGNATURE SLICING ═════════════════════════════════════════════════\n\n    /// @notice Unpacks signature payload into (r, s, v) parameters.\n    /// @dev Make sure to verify signature length with isSignature() beforehand.\n    function toRSV(Signature signature) internal pure returns (bytes32 r, bytes32 s, uint8 v) {\n        // Get the underlying memory view\n        MemView memView = unwrap(signature);\n        r = memView.index({index_: OFFSET_R, bytes_: 32});\n        s = memView.index({index_: OFFSET_S, bytes_: 32});\n        // Can be safely casted to uint8, since we index a single byte\n        v = uint8(memView.indexUint({index_: OFFSET_V, bytes_: 1}));\n    }\n\n    // ═════════════════════════════════════════════════ CALLDATA ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Constructs the calldata with the modified arguments:\n     * the existing arguments are prepended with the arguments from the prefix.\n     * @dev Given:\n     *  - `calldata = abi.encodeWithSelector(foo.selector, d, e);`\n     *  - `prefix = abi.encode(a, b, c);`\n     *  - `a`, `b`, `c` are arguments of static type (i.e. not dynamically sized ones)\n     *      Then:\n     *  - Function will return abi.encodeWithSelector(foo.selector, a, c, c, d, e)\n     *  - Returned calldata will trigger `foo(a, b, c, d, e)` when used for a contract call.\n     * Note: for clarification as to what types are considered static, see\n     * https://docs.soliditylang.org/en/latest/abi-spec.html#formal-specification-of-the-encoding\n     * @param callData  Calldata that needs to be modified\n     * @param prefix    ABI-encoded arguments to use as the first arguments in the new calldata\n     * @return Modified calldata having prefix as the first arguments.\n     */\n    function addPrefix(CallData callData, bytes memory prefix) internal view returns (bytes memory) {\n        // Prefix should occupy a whole amount of words in memory\n        if (!_fullWords(prefix.length)) revert UnformattedCallDataPrefix();\n        MemView[] memory views = new MemView[](3);\n        // Use payload's function selector\n        views[0] = abi.encodePacked(callData.callSelector()).ref();\n        // Use prefix as the first arguments\n        views[1] = prefix.ref();\n        // Use payload's remaining arguments\n        views[2] = callData.arguments();\n        return MemViewLib.join(views);\n    }\n\n    /**\n     * @notice Returns a CallData view over for the given payload.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(bytes memory payload) internal pure returns (CallData) {\n        return castToCallData(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a CallData view.\n     * @dev Will revert if the memory view is not over a calldata.\n     */\n    function castToCallData(MemView memView) internal pure returns (CallData) {\n        if (!isCallData(memView)) revert UnformattedCallData();\n        return CallData.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a byte string is a valid calldata, i.e.\n     * a function selector, followed by arbitrary amount of arguments.\n     */\n    function isCallData(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Calldata should at least have a function selector\n        if (length \u003c SELECTOR_LENGTH) return false;\n        // The remainder of the calldata should be exactly N memory words (N \u003e= 0)\n        return _fullWords(length - SELECTOR_LENGTH);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(CallData callData) internal pure returns (MemView) {\n        return MemView.wrap(CallData.unwrap(callData));\n    }\n\n    /// @notice Returns callData's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(CallData callData) internal pure returns (bytes32) {\n        return callData.unwrap().keccak();\n    }\n\n    // ═════════════════════════════════════════════ CALLDATA SLICING ══════════════════════════════════════════════════\n\n    /**\n     * @notice Returns amount of memory words (32 byte chunks) the function arguments\n     * occupy in the calldata.\n     * @dev This might differ from amount of arguments supplied, if any of the arguments\n     * occupies more than one memory slot. It is true, however, that argument part of the payload\n     * occupies exactly N words, even for dynamic types like `bytes`\n     */\n    function argumentWords(CallData callData) internal pure returns (uint256) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        // Equivalent of (length - SELECTOR_LENGTH) / 32\n        return (memView.len() - SELECTOR_LENGTH) \u003e\u003e 5;\n    }\n\n    /// @notice Returns selector for the provided calldata.\n    function callSelector(CallData callData) internal pure returns (bytes4) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return bytes4(memView.index({index_: OFFSET_SELECTOR, bytes_: SELECTOR_LENGTH}));\n    }\n\n    /// @notice Returns abi encoded arguments for the provided calldata.\n    function arguments(CallData callData) internal pure returns (MemView) {\n        // Get the underlying memory view\n        MemView memView = unwrap(callData);\n        return memView.sliceFrom({index_: OFFSET_ARGUMENTS});\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Checks if length is full amount of memory words (32 bytes).\n    function _fullWords(uint256 length) internal pure returns (bool) {\n        // The equivalent of length % 32 == 0\n        return length \u0026 31 == 0;\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n    function __Context_init() internal onlyInitializing {\n    }\n\n    function __Context_init_unchained() internal onlyInitializing {\n    }\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[50] private __gap;\n}\n\n// contracts/libs/merkle/MerkleTree.sol\n\n/// `BaseTree` is a struct representing incremental merkle tree.\n/// - Contains only the current branch.\n/// - The number of inserted leaves is stored externally, and is later supplied for tree operations.\n/// - Has a fixed height of `ORIGIN_TREE_HEIGHT`.\n/// - Can store up to `2 ** ORIGIN_TREE_HEIGHT - 1` leaves.\n/// \u003e Note: the hash function for the tree `H(x, y)` is defined as:\n/// \u003e - `H(0,0) = 0`\n/// \u003e - `H(x,y) = keccak256(x, y), when (x != 0 || y != 0)`\n/// ## Invariant for leafs\n/// - The leftmost empty leaf has `index == count`, where `count` is the amount of the inserted leafs so far.\n/// - Value for any empty leaf or node is bytes32(0).\n/// ## Invariant for current branch\n/// `branch[i]` is always the value of a node on the i-th level.\n/// Levels are numbered from leafs to root: `0 .. ORIGIN_TREE_HEIGHT`.\n/// `branch[i]` stores the value for the node, such that:\n//  - The node is a \"left child\" (e.g. has an even index).\n/// - The node must have two non-empty children.\n/// - Out of all level's \"left child\" nodes with \"non-empty children\",\n/// the one with the biggest index (the rightmost one) is stored as `branch[i]`.\n/// \u003e __`branch` could be used to form a proof of inclusion for the first empty leaf (`index == count`).__\n/// _Here is how:_\n/// - Let's walk along the path from the \"first empty leaf\" to the root.\n/// - i-th bit of the \"first empty leaf\" index (which is equal to `count`) determines if the path's node\n/// for this i-th level is a \"left child\" or a \"right child\".\n/// - i-th bit in `count` is 0 → we are the left child on this level → sibling is the right child\n/// that does not exist yet → `proof[i] = bytes32(0)`.\n/// - i-th bit in `count` is 1 → we are the right child on this level → sibling is the left child\n/// sibling is the rightmost \"left child\" node on the level → `proof[i] = branch[i]`.\n/// \u003e Therefore `proof[i] = (count \u0026 (1 \u003c\u003c i)) == 0 ? bytes32(0) : branch[i])`\nstruct BaseTree {\n    bytes32[ORIGIN_TREE_HEIGHT] branch;\n}\n\nusing MerkleTree for BaseTree global;\n\n/// `HistoricalTree` is an incremental merkle tree keeping track of its historical merkle roots.\n/// \u003e - `roots[N]` is the root of the tree after `N` leafs were inserted\n/// \u003e - `roots[0] == bytes32(0)`\n/// @param tree     Incremental merkle tree\n/// @param roots    Historical merkle roots of the tree\nstruct HistoricalTree {\n    BaseTree tree;\n    bytes32[] roots;\n}\n\nusing MerkleTree for HistoricalTree global;\n\n/// `DynamicTree` is a struct representing a Merkle Tree with `2**AGENT_TREE_HEIGHT` leaves.\n/// - A single operation is available: update value for leaf with an arbitrary index (which might be a non-empty leaf).\n/// - This is done by requesting the proof of inclusion for the old value, which is used to both\n/// verify the old value, and calculate the new root.\n/// \u003e Based on Original idea from [ER forum post](https://ethresear.ch/t/efficient-on-chain-dynamic-merkle-tree/11054).\nstruct DynamicTree {\n    bytes32 root;\n}\n\nusing MerkleTree for DynamicTree global;\n\n/// MerkleTree is work based on Nomad's Merkle.sol, which is used under MIT OR Apache-2.0\n/// [link](https://github.com/nomad-xyz/monorepo/blob/main/packages/contracts-core/contracts/libs/Merkle.sol).\n/// With the following changes:\n/// - Adapted for Solidity 0.8.x.\n/// - Amount of tree leaves stored externally.\n/// - Added thorough documentation.\n/// - `H(0,0) = 0` optimization from [ER forum post](https://ethresear.ch/t/optimizing-sparse-merkle-trees/3751/6).\n/// \u003e Nomad's Merkle.sol is work based on eth2 deposit contract, which is used under CC0-1.0\n///[link](https://github.com/ethereum/deposit_contract/blob/dev/deposit_contract/contracts/validator_registration.v.py).\n/// With the following changes:\n/// \u003e - Implemented in Solidity 0.7.6 (eth2 deposit contract implemented in Vyper).\n/// \u003e - `H() = keccak256()` is used as the hashing function instead of `sha256()`.\nlibrary MerkleTree {\n    /// @dev For root calculation we need at least one empty leaf, thus the minus one in the formula.\n    uint256 internal constant MAX_LEAVES = 2 ** ORIGIN_TREE_HEIGHT - 1;\n\n    // ═════════════════════════════════════════════════ BASE TREE ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Inserts `node` into merkle tree\n     * @dev Reverts if tree is full\n     * @param newCount  Amount of inserted leaves in the tree after the insertion (i.e. current + 1)\n     * @param node      Element to insert into tree\n     */\n    function insertBase(BaseTree storage tree, uint256 newCount, bytes32 node) internal {\n        if (newCount \u003e MAX_LEAVES) revert MerkleTreeFull();\n        // We go up the tree following the branch from the empty leaf AFTER the just inserted one.\n        // We stop when we find the first \"right child\" node.\n        // Its sibling is now the rightmost \"left child\" node that has two non-empty children.\n        // Therefore we need to update `tree.branch` value on this level.\n        // One could see that `tree.branch` value on lower and higher levels remain unchanged.\n\n        // Loop invariant: `node` is the current level's value for the branch from JUST INSERTED leaf\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            if ((newCount \u0026 1) == 1) {\n                // Found the first \"right child\" node on the branch from EMPTY leaf\n                // `node` is the value for node on branch from JUST INSERTED leaf\n                // Which in this case is the \"left child\".\n                // We update tree.branch and exit\n                tree.branch[i] = node;\n                return;\n            }\n            // On the branch from EMPTY leaf this is still a \"left child\".\n            // Meaning on branch from JUST INSERTED leaf, `node` is a right child.\n            // We compute value for `node` parent using `tree.branch` invariant:\n            // This is the rightmost \"left child\" node, which would be sibling of `node`.\n            node = MerkleMath.getParent(tree.branch[i], node);\n            // Get the parent index, and go to the next tree level\n            newCount \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n        // As the loop should always end prematurely with the `return` statement,\n        // this code should be unreachable. We assert `false` just to be safe.\n        assert(false);\n    }\n\n    /**\n     * @notice Calculates and returns current root of the merkle tree.\n     * @param count     Current amount of inserted leaves in the tree\n     * @return current  Calculated root of `tree`\n     */\n    function rootBase(BaseTree storage tree, uint256 count) internal view returns (bytes32 current) {\n        // To calculate the root we follow the branch of first EMPTY leaf (index == count)\n        for (uint256 i = 0; i \u003c ORIGIN_TREE_HEIGHT;) {\n            // Check if we are the left or the right child on the current level\n            if ((count \u0026 1) == 1) {\n                // We are the right child. Our sibling is the \"rightmost\" \"left-child\" node\n                // that has two non-empty children → sibling is `tree.branch[i]`\n                current = MerkleMath.getParent(tree.branch[i], current);\n            } else {\n                // We are the left child. Our sibling does not exist yet → sibling is EMPTY\n                current = MerkleMath.getParent(current, bytes32(0));\n            }\n            // Get the parent index, and go to the next tree level\n            count \u003e\u003e= 1;\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    // ══════════════════════════════════════════════ HISTORICAL TREE ══════════════════════════════════════════════════\n\n    /// @notice Initializes the historical roots for the tree by inserting an empty root.\n    // solhint-disable-next-line ordering\n    function initializeRoots(HistoricalTree storage tree) internal returns (bytes32 savedRoot) {\n        // This should only be called once, when the contract is initialized\n        assert(tree.roots.length == 0);\n        // Save root for empty merkle tree: bytes32(0)\n        tree.roots.push(savedRoot);\n    }\n\n    /// @notice Inserts a new leaf into the merkle tree.\n    /// @dev Reverts if tree is full.\n    /// @param node         Element to insert into tree\n    /// @return newRoot     Merkle root after the leaf was inserted\n    function insert(HistoricalTree storage tree, bytes32 node) internal returns (bytes32 newRoot) {\n        // Tree count after the new leaf will be inserted (we store roots[0] as root of empty tree)\n        uint256 newCount = tree.roots.length;\n        tree.tree.insertBase(newCount, node);\n        // Save the new root\n        newRoot = tree.tree.rootBase(newCount);\n        tree.roots.push(newRoot);\n    }\n\n    /// @notice Returns the historical root of the merkle tree.\n    /// @dev Reverts if not enough leafs have been inserted.\n    /// @param count            Amount of leafs in the tree at some point of time\n    /// @return historicalRoot  Merkle root after `count` leafs were inserted\n    function root(HistoricalTree storage tree, uint256 count) internal view returns (bytes32 historicalRoot) {\n        if (count \u003e= tree.roots.length) revert NotEnoughLeafs();\n        return tree.roots[count];\n    }\n\n    // ═══════════════════════════════════════════════ DYNAMIC TREE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Updates the value for the leaf with the given index in the Dynamic Merkle Tree.\n     * @dev Will revert if incorrect proof of inclusion for old value is supplied.\n     * @param tree          Dynamic merkle tree\n     * @param index         Index of the leaf to update\n     * @param oldValue      Previous value of the leaf\n     * @param branch        Proof of inclusion of previous value into the tree\n     * @param newValue      New leaf value to assign\n     * @return newRoot      New value for the Merkle Root after the leaf is updated\n     */\n    function update(\n        DynamicTree storage tree,\n        uint256 index,\n        bytes32 oldValue,\n        bytes32[] memory branch,\n        bytes32 newValue\n    ) internal returns (bytes32 newRoot) {\n        // Check that the old value + proof result in a correct root\n        if (MerkleMath.proofRoot(index, oldValue, branch, AGENT_TREE_HEIGHT) != tree.root) {\n            revert LeafNotProven();\n        }\n        // New root is new value + the same proof (values for sibling nodes are not updated)\n        newRoot = MerkleMath.proofRoot(index, newValue, branch, AGENT_TREE_HEIGHT);\n        // Write the new root\n        tree.root = newRoot;\n    }\n}\n\n// contracts/libs/stack/Tips.sol\n\n/// Tips is encoded data with \"tips paid for sending a base message\".\n/// Note: even though uint256 is also an underlying type for MemView, Tips is stored ON STACK.\ntype Tips is uint256;\n\nusing TipsLib for Tips global;\n\n/// # Tips\n/// Library for formatting _the tips part_ of _the base messages_.\n///\n/// ## How the tips are awarded\n/// Tips are paid for sending a base message, and are split across all the agents that\n/// made the message execution on destination chain possible.\n/// ### Summit tips\n/// Split between:\n///     - Guard posting a snapshot with state ST_G for the origin chain.\n///     - Notary posting a snapshot SN_N using ST_G. This creates attestation A.\n///     - Notary posting a message receipt after it is executed on destination chain.\n/// ### Attestation tips\n/// Paid to:\n///     - Notary posting attestation A to destination chain.\n/// ### Execution tips\n/// Paid to:\n///     - First executor performing a valid execution attempt (correct proofs, optimistic period over),\n///      using attestation A to prove message inclusion on origin chain, whether the recipient reverted or not.\n/// ### Delivery tips.\n/// Paid to:\n///     - Executor who successfully executed the message on destination chain.\n///\n/// ## Tips encoding\n/// - Tips occupy a single storage word, and thus are stored on stack instead of being stored in memory.\n/// - The actual tip values should be determined by multiplying stored values by divided by TIPS_MULTIPLIER=2**32.\n/// - Tips are packed into a single word of storage, while allowing real values up to ~8*10**28 for every tip category.\n/// \u003e The only downside is that the \"real tip values\" are now multiplies of ~4*10**9, which should be fine even for\n/// the chains with the most expensive gas currency.\n/// # Tips stack layout (from highest bits to lowest)\n///\n/// | Position   | Field          | Type   | Bytes | Description                                                |\n/// | ---------- | -------------- | ------ | ----- | ---------------------------------------------------------- |\n/// | (032..024] | summitTip      | uint64 | 8     | Tip for agents interacting with Summit contract            |\n/// | (024..016] | attestationTip | uint64 | 8     | Tip for Notary posting attestation to Destination contract |\n/// | (016..008] | executionTip   | uint64 | 8     | Tip for valid execution attempt on destination chain       |\n/// | (008..000] | deliveryTip    | uint64 | 8     | Tip for successful message delivery on destination chain   |\n\nlibrary TipsLib {\n    using SafeCast for uint256;\n\n    /// @dev Amount of bits to shift to summitTip field\n    uint256 private constant SHIFT_SUMMIT_TIP = 24 * 8;\n    /// @dev Amount of bits to shift to attestationTip field\n    uint256 private constant SHIFT_ATTESTATION_TIP = 16 * 8;\n    /// @dev Amount of bits to shift to executionTip field\n    uint256 private constant SHIFT_EXECUTION_TIP = 8 * 8;\n\n    // ═══════════════════════════════════════════════════ TIPS ════════════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips with the given fields\n    /// @param summitTip_        Tip for agents interacting with Summit contract, divided by TIPS_MULTIPLIER\n    /// @param attestationTip_   Tip for Notary posting attestation to Destination contract, divided by TIPS_MULTIPLIER\n    /// @param executionTip_     Tip for valid execution attempt on destination chain, divided by TIPS_MULTIPLIER\n    /// @param deliveryTip_      Tip for successful message delivery on destination chain, divided by TIPS_MULTIPLIER\n    function encodeTips(uint64 summitTip_, uint64 attestationTip_, uint64 executionTip_, uint64 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // forgefmt: disable-next-item\n        return Tips.wrap(\n            uint256(summitTip_) \u003c\u003c SHIFT_SUMMIT_TIP |\n            uint256(attestationTip_) \u003c\u003c SHIFT_ATTESTATION_TIP |\n            uint256(executionTip_) \u003c\u003c SHIFT_EXECUTION_TIP |\n            uint256(deliveryTip_)\n        );\n    }\n\n    /// @notice Convenience function to encode tips with uint256 values.\n    function encodeTips256(uint256 summitTip_, uint256 attestationTip_, uint256 executionTip_, uint256 deliveryTip_)\n        internal\n        pure\n        returns (Tips)\n    {\n        // In practice, the tips amounts are not supposed to be higher than 2**96, and with 32 bits of granularity\n        // using uint64 is enough to store the values. However, we still check for overflow just in case.\n        // TODO: consider using Number type to store the tips values.\n        return encodeTips({\n            summitTip_: (summitTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            attestationTip_: (attestationTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            executionTip_: (executionTip_ \u003e\u003e TIPS_GRANULARITY).toUint64(),\n            deliveryTip_: (deliveryTip_ \u003e\u003e TIPS_GRANULARITY).toUint64()\n        });\n    }\n\n    /// @notice Wraps the padded encoded tips into a Tips-typed value.\n    /// @dev There is no actual padding here, as the underlying type is already uint256,\n    /// but we include this function for consistency and to be future-proof, if tips will eventually use anything\n    /// smaller than uint256.\n    function wrapPadded(uint256 paddedTips) internal pure returns (Tips) {\n        return Tips.wrap(paddedTips);\n    }\n\n    /**\n     * @notice Returns a formatted Tips payload specifying empty tips.\n     * @return Formatted tips\n     */\n    function emptyTips() internal pure returns (Tips) {\n        return Tips.wrap(0);\n    }\n\n    /// @notice Returns tips's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(Tips tips) internal pure returns (bytes32 hashedTips) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Store tips in scratch space\n            mstore(0, tips)\n            // Compute hash of tips padded to 32 bytes\n            hashedTips := keccak256(0, 32)\n        }\n    }\n\n    // ═══════════════════════════════════════════════ TIPS SLICING ════════════════════════════════════════════════════\n\n    /// @notice Returns summitTip field\n    function summitTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_SUMMIT_TIP);\n    }\n\n    /// @notice Returns attestationTip field\n    function attestationTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_ATTESTATION_TIP);\n    }\n\n    /// @notice Returns executionTip field\n    function executionTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips) \u003e\u003e SHIFT_EXECUTION_TIP);\n    }\n\n    /// @notice Returns deliveryTip field\n    function deliveryTip(Tips tips) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Tips.unwrap(tips));\n    }\n\n    // ════════════════════════════════════════════════ TIPS VALUE ═════════════════════════════════════════════════════\n\n    /// @notice Returns total value of the tips payload.\n    /// This is the sum of the encoded values, scaled up by TIPS_MULTIPLIER\n    function value(Tips tips) internal pure returns (uint256 value_) {\n        value_ = uint256(tips.summitTip()) + tips.attestationTip() + tips.executionTip() + tips.deliveryTip();\n        value_ \u003c\u003c= TIPS_GRANULARITY;\n    }\n\n    /// @notice Increases the delivery tip to match the new value.\n    function matchValue(Tips tips, uint256 newValue) internal pure returns (Tips newTips) {\n        uint256 oldValue = tips.value();\n        if (newValue \u003c oldValue) revert TipsValueTooLow();\n        // We want to increase the delivery tip, while keeping the other tips the same\n        unchecked {\n            uint256 delta = (newValue - oldValue) \u003e\u003e TIPS_GRANULARITY;\n            // `delta` fits into uint224, as TIPS_GRANULARITY is 32, so this never overflows uint256.\n            // In practice, this will never overflow uint64 as well, but we still check it just in case.\n            if (delta + tips.deliveryTip() \u003e type(uint64).max) revert TipsOverflow();\n            // Delivery tips occupy lowest 8 bytes, so we can just add delta to the tips value\n            // to effectively increase the delivery tip (knowing that delta fits into uint64).\n            newTips = Tips.wrap(Tips.unwrap(tips) + delta);\n        }\n    }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    function __Ownable_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable_init_unchained() internal onlyInitializing {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n    function __Ownable2Step_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable2Step_init_unchained() internal onlyInitializing {\n    }\n    address private _pendingOwner;\n\n    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Returns the address of the pending owner.\n     */\n    function pendingOwner() public view virtual returns (address) {\n        return _pendingOwner;\n    }\n\n    /**\n     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual override onlyOwner {\n        _pendingOwner = newOwner;\n        emit OwnershipTransferStarted(owner(), newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual override {\n        delete _pendingOwner;\n        super._transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev The new owner accepts the ownership transfer.\n     */\n    function acceptOwnership() public virtual {\n        address sender = _msgSender();\n        require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n        _transferOwnership(sender);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n\n// contracts/libs/memory/State.sol\n\n/// State is a memory view over a formatted state payload.\ntype State is uint256;\n\nusing StateLib for State global;\n\n/// # State\n/// State structure represents the state of Origin contract at some point of time.\n/// - State is structured in a way to track the updates of the Origin Merkle Tree.\n/// - State includes root of the Origin Merkle Tree, origin domain and some additional metadata.\n/// ## Origin Merkle Tree\n/// Hash of every sent message is inserted in the Origin Merkle Tree, which changes\n/// the value of Origin Merkle Root (which is the root for the mentioned tree).\n/// - Origin has a single Merkle Tree for all messages, regardless of their destination domain.\n/// - This leads to Origin state being updated if and only if a message was sent in a block.\n/// - Origin contract is a \"source of truth\" for states: a state is considered \"valid\" in its Origin,\n/// if it matches the state of the Origin contract after the N-th (nonce) message was sent.\n///\n/// # Memory layout of State fields\n///\n/// | Position   | Field       | Type    | Bytes | Description                    |\n/// | ---------- | ----------- | ------- | ----- | ------------------------------ |\n/// | [000..032) | root        | bytes32 | 32    | Root of the Origin Merkle Tree |\n/// | [032..036) | origin      | uint32  | 4     | Domain where Origin is located |\n/// | [036..040) | nonce       | uint32  | 4     | Amount of sent messages        |\n/// | [040..045) | blockNumber | uint40  | 5     | Block of last sent message     |\n/// | [045..050) | timestamp   | uint40  | 5     | Time of last sent message      |\n/// | [050..062) | gasData     | uint96  | 12    | Gas data for the chain         |\n///\n/// @dev State could be used to form a Snapshot to be signed by a Guard or a Notary.\nlibrary StateLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_ROOT = 0;\n    uint256 private constant OFFSET_ORIGIN = 32;\n    uint256 private constant OFFSET_NONCE = 36;\n    uint256 private constant OFFSET_BLOCK_NUMBER = 40;\n    uint256 private constant OFFSET_TIMESTAMP = 45;\n    uint256 private constant OFFSET_GAS_DATA = 50;\n\n    // ═══════════════════════════════════════════════════ STATE ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted State payload with provided fields\n     * @param root_         New merkle root\n     * @param origin_       Domain of Origin's chain\n     * @param nonce_        Nonce of the merkle root\n     * @param blockNumber_  Block number when root was saved in Origin\n     * @param timestamp_    Block timestamp when root was saved in Origin\n     * @param gasData_      Gas data for the chain\n     * @return Formatted state\n     */\n    function formatState(\n        bytes32 root_,\n        uint32 origin_,\n        uint32 nonce_,\n        uint40 blockNumber_,\n        uint40 timestamp_,\n        GasData gasData_\n    ) internal pure returns (bytes memory) {\n        return abi.encodePacked(root_, origin_, nonce_, blockNumber_, timestamp_, gasData_);\n    }\n\n    /**\n     * @notice Returns a State view over the given payload.\n     * @dev Will revert if the payload is not a state.\n     */\n    function castToState(bytes memory payload) internal pure returns (State) {\n        return castToState(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a State view.\n     * @dev Will revert if the memory view is not over a state.\n     */\n    function castToState(MemView memView) internal pure returns (State) {\n        if (!isState(memView)) revert UnformattedState();\n        return State.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted State.\n    function isState(MemView memView) internal pure returns (bool) {\n        return memView.len() == STATE_LENGTH;\n    }\n\n    /// @notice Returns the hash of a State, that could be later signed by a Guard to signal\n    /// that the state is invalid.\n    function hashInvalid(State state) internal pure returns (bytes32) {\n        // The final hash to sign is keccak(stateInvalidSalt, keccak(state))\n        return state.unwrap().keccakSalted(STATE_INVALID_SALT);\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(State state) internal pure returns (MemView) {\n        return MemView.wrap(State.unwrap(state));\n    }\n\n    /// @notice Compares two State structures.\n    function equals(State a, State b) internal pure returns (bool) {\n        // Length of a State payload is fixed, so we just need to compare the hashes\n        return a.unwrap().keccak() == b.unwrap().keccak();\n    }\n\n    // ═══════════════════════════════════════════════ STATE HASHING ═══════════════════════════════════════════════════\n\n    /// @notice Returns the hash of the State.\n    /// @dev We are using the Merkle Root of a tree with two leafs (see below) as state hash.\n    function leaf(State state) internal pure returns (bytes32) {\n        (bytes32 leftLeaf_, bytes32 rightLeaf_) = state.subLeafs();\n        // Final hash is the parent of these leafs\n        return keccak256(bytes.concat(leftLeaf_, rightLeaf_));\n    }\n\n    /// @notice Returns \"sub-leafs\" of the State. Hash of these \"sub leafs\" is going to be used\n    /// as a \"state leaf\" in the \"Snapshot Merkle Tree\".\n    /// This enables proving that leftLeaf = (root, origin) was a part of the \"Snapshot Merkle Tree\",\n    /// by combining `rightLeaf` with the remainder of the \"Snapshot Merkle Proof\".\n    function subLeafs(State state) internal pure returns (bytes32 leftLeaf_, bytes32 rightLeaf_) {\n        MemView memView = state.unwrap();\n        // Left leaf is (root, origin)\n        leftLeaf_ = memView.prefix({len_: OFFSET_NONCE}).keccak();\n        // Right leaf is (metadata), or (nonce, blockNumber, timestamp)\n        rightLeaf_ = memView.sliceFrom({index_: OFFSET_NONCE}).keccak();\n    }\n\n    /// @notice Returns the left \"sub-leaf\" of the State.\n    function leftLeaf(bytes32 root_, uint32 origin_) internal pure returns (bytes32) {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(root_, origin_));\n    }\n\n    /// @notice Returns the right \"sub-leaf\" of the State.\n    function rightLeaf(uint32 nonce_, uint40 blockNumber_, uint40 timestamp_, GasData gasData_)\n        internal\n        pure\n        returns (bytes32)\n    {\n        // We use encodePacked here to simulate the State memory layout\n        return keccak256(abi.encodePacked(nonce_, blockNumber_, timestamp_, gasData_));\n    }\n\n    // ═══════════════════════════════════════════════ STATE SLICING ═══════════════════════════════════════════════════\n\n    /// @notice Returns a historical Merkle root from the Origin contract.\n    function root(State state) internal pure returns (bytes32) {\n        return state.unwrap().index({index_: OFFSET_ROOT, bytes_: 32});\n    }\n\n    /// @notice Returns domain of chain where the Origin contract is deployed.\n    function origin(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_ORIGIN, bytes_: 4}));\n    }\n\n    /// @notice Returns nonce of Origin contract at the time, when `root` was the Merkle root.\n    function nonce(State state) internal pure returns (uint32) {\n        // Can be safely casted to uint32, since we index 4 bytes\n        return uint32(state.unwrap().indexUint({index_: OFFSET_NONCE, bytes_: 4}));\n    }\n\n    /// @notice Returns a block number when `root` was saved in Origin.\n    function blockNumber(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_BLOCK_NUMBER, bytes_: 5}));\n    }\n\n    /// @notice Returns a block timestamp when `root` was saved in Origin.\n    /// @dev This is the timestamp according to the origin chain.\n    function timestamp(State state) internal pure returns (uint40) {\n        // Can be safely casted to uint40, since we index 5 bytes\n        return uint40(state.unwrap().indexUint({index_: OFFSET_TIMESTAMP, bytes_: 5}));\n    }\n\n    /// @notice Returns gas data for the chain.\n    function gasData(State state) internal pure returns (GasData) {\n        return GasDataLib.wrapGasData(state.unwrap().indexUint({index_: OFFSET_GAS_DATA, bytes_: GAS_DATA_LENGTH}));\n    }\n}\n\n// contracts/libs/memory/BaseMessage.sol\n\n/// BaseMessage is a memory view over the base message supported by Origin-Destination\ntype BaseMessage is uint256;\n\nusing BaseMessageLib for BaseMessage global;\n\n/// BaseMessage structure represents a base message sent via the Origin-Destination contracts.\n/// - It only contains data relevant to the base message, the rest of data is encoded in the message header.\n/// - `sender` and `recipient` for EVM chains are EVM addresses casted to bytes32, while preserving left-alignment.\n/// - `tips` and `request` parameters are specified by a message sender\n/// \u003e Origin will calculate minimum tips for given request and content length, and will reject messages with tips\n/// lower than that.\n///\n/// # Memory layout of BaseMessage fields\n///\n/// | Position   | Field     | Type    | Bytes | Description                            |\n/// | ---------- | --------- | ------- | ----- | -------------------------------------- |\n/// | [000..032) | tips      | uint256 | 32    | Encoded tips paid on origin chain      |\n/// | [032..064) | sender    | bytes32 | 32    | Sender address on origin chain         |\n/// | [064..096) | recipient | bytes32 | 32    | Recipient address on destination chain |\n/// | [096..116) | request   | uint160 | 20    | Encoded request for message execution  |\n/// | [104..AAA) | content   | bytes   | ??    | Content to be passed to recipient      |\nlibrary BaseMessageLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_TIPS = 0;\n    uint256 private constant OFFSET_SENDER = 32;\n    uint256 private constant OFFSET_RECIPIENT = 64;\n    uint256 private constant OFFSET_REQUEST = OFFSET_RECIPIENT + TIPS_LENGTH;\n    uint256 private constant OFFSET_CONTENT = OFFSET_REQUEST + REQUEST_LENGTH;\n\n    // ═══════════════════════════════════════════════ BASE MESSAGE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted BaseMessage payload with provided fields.\n     * @param tips_         Encoded tips information\n     * @param sender_       Sender address on origin chain\n     * @param recipient_    Recipient address on destination chain\n     * @param request_      Encoded request for message execution\n     * @param content_      Raw content to be passed to recipient on destination chain\n     * @return Formatted base message\n     */\n    function formatBaseMessage(Tips tips_, bytes32 sender_, bytes32 recipient_, Request request_, bytes memory content_)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return abi.encodePacked(tips_, sender_, recipient_, request_, content_);\n    }\n\n    /**\n     * @notice Returns a BaseMessage view over the given payload.\n     * @dev Will revert if the payload is not a base message.\n     */\n    function castToBaseMessage(bytes memory payload) internal pure returns (BaseMessage) {\n        return castToBaseMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a BaseMessage view.\n     * @dev Will revert if the memory view is not over a base message payload.\n     */\n    function castToBaseMessage(MemView memView) internal pure returns (BaseMessage) {\n        if (!isBaseMessage(memView)) revert UnformattedBaseMessage();\n        return BaseMessage.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted BaseMessage.\n    function isBaseMessage(MemView memView) internal pure returns (bool) {\n        // Check if sender, recipient, tips fields exist\n        return (memView.len() \u003e= OFFSET_CONTENT);\n        // Content could be empty, so we don't check that\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(BaseMessage baseMessage) internal pure returns (MemView) {\n        return MemView.wrap(BaseMessage.unwrap(baseMessage));\n    }\n\n    /// @notice Returns baseMessage's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        // We hash \"tips\" and \"everything but tips\" to make tips proofs easier to verify\n        return MerkleMath.getParent(baseMessage.tips().leaf(), baseMessage.bodyLeaf());\n    }\n\n    /// @notice Returns hash for the \"everything but tips\" part of the base message.\n    function bodyLeaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_SENDER}).keccak();\n    }\n\n    // ═══════════════════════════════════════════ BASE MESSAGE SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips paid on origin chain.\n    function tips(BaseMessage baseMessage) internal pure returns (Tips) {\n        return TipsLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_TIPS, bytes_: TIPS_LENGTH})));\n    }\n\n    /// @notice Returns sender address on origin chain.\n    function sender(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_SENDER, bytes_: 32});\n    }\n\n    /// @notice Returns recipient address on destination chain.\n    function recipient(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_RECIPIENT, bytes_: 32});\n    }\n\n    /// @notice Returns an encoded request for message execution on destination chain.\n    function request(BaseMessage baseMessage) internal pure returns (Request) {\n        return RequestLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_REQUEST, bytes_: REQUEST_LENGTH})));\n    }\n\n    /// @notice Returns an untyped memory view over the content to be passed to recipient.\n    function content(BaseMessage baseMessage) internal pure returns (MemView) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_CONTENT});\n    }\n}\n\n// contracts/base/MessagingBase.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for all messaging contracts.\n * - Provides context on the local chain's domain.\n * - Provides ownership functionality.\n * - Will be providing pausing functionality when it is implemented.\n */\nabstract contract MessagingBase is MultiCallable, Versioned, Ownable2StepUpgradeable {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @notice Domain of the local chain, set once upon contract creation\n    uint32 public immutable localDomain;\n    // @notice Domain of the Synapse chain, set once upon contract creation\n    uint32 public immutable synapseDomain;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev gap for upgrade safety\n    uint256[50] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    constructor(string memory version_, uint32 synapseDomain_) Versioned(version_) {\n        localDomain = ChainContext.chainId();\n        synapseDomain = synapseDomain_;\n    }\n\n    // TODO: Implement pausing\n\n    /**\n     * @dev Should be impossible to renounce ownership;\n     * we override OpenZeppelin OwnableUpgradeable's\n     * implementation of renounceOwnership to make it a no-op\n     */\n    function renounceOwnership() public override onlyOwner {} //solhint-disable-line no-empty-blocks\n}\n\n// contracts/libs/memory/Message.sol\n\n/// Message is a memory over over a formatted message payload.\ntype Message is uint256;\n\nusing MessageLib for Message global;\n\n/// Library for formatting the various messages supported by Origin and Destination.\n///\n/// # Message memory layout\n///\n/// | Position   | Field  | Type    | Bytes | Description                                             |\n/// | ---------- | ------ | ------- | ----- | ------------------------------------------------------- |\n/// | [000..017) | header | uint136 | 17    | Encoded general routing information for the message     |\n/// | [017..AAA) | body   | bytes   | ??    | Formatted payload (according to flag) with message body |\nlibrary MessageLib {\n    using BaseMessageLib for MemView;\n    using ByteString for MemView;\n    using MemViewLib for bytes;\n    using HeaderLib for MemView;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_HEADER = 0;\n    uint256 private constant OFFSET_BODY = OFFSET_HEADER + HEADER_LENGTH;\n\n    // ══════════════════════════════════════════════════ MESSAGE ══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns formatted message with provided fields.\n     * @param header_   Encoded general routing information for the message\n     * @param body_     Formatted payload (according to flag) with message body\n     * @return Formatted message\n     */\n    function formatMessage(Header header_, bytes memory body_) internal pure returns (bytes memory) {\n        return abi.encodePacked(header_, body_);\n    }\n\n    /**\n     * @notice Returns a Message view over for the given payload.\n     * @dev Will revert if the payload is not a message payload.\n     */\n    function castToMessage(bytes memory payload) internal pure returns (Message) {\n        return castToMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a Message view.\n     * @dev Will revert if the memory view is not over a message payload.\n     */\n    function castToMessage(MemView memView) internal pure returns (Message) {\n        if (!isMessage(memView)) revert UnformattedMessage();\n        return Message.wrap(MemView.unwrap(memView));\n    }\n\n    /**\n     * @notice Checks that a payload is a formatted Message.\n     */\n    function isMessage(MemView memView) internal pure returns (bool) {\n        uint256 length = memView.len();\n        // Check if headers exist in the payload\n        if (length \u003c OFFSET_BODY) return false;\n        // Check that Header is valid\n        uint256 paddedHeader = _header(memView);\n        if (!HeaderLib.isHeader(paddedHeader)) return false;\n        // Check that body is formatted according to the flag\n        // Only Base/Manager message flags exist\n        if (HeaderLib.wrapPadded(paddedHeader).flag() == MessageFlag.Base) {\n            // Check if body is a formatted base message\n            return _body(memView).isBaseMessage();\n        } else {\n            // Check if body is a formatted calldata for AgentManager call\n            return _body(memView).isCallData();\n        }\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(Message message) internal pure returns (MemView) {\n        return MemView.wrap(Message.unwrap(message));\n    }\n\n    /// @notice Returns message's hash: a leaf to be inserted in the Merkle tree.\n    function leaf(Message message) internal pure returns (bytes32) {\n        // We hash header and body separately to make message proofs easier to verify\n        Header header_ = message.header();\n        // Only Base/Manager message flags exist\n        if (header_.flag() == MessageFlag.Base) {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToBaseMessage().leaf());\n        } else {\n            return MerkleMath.getParent(header_.leaf(), message.body().castToCallData().leaf());\n        }\n    }\n\n    // ══════════════════════════════════════════════ MESSAGE SLICING ══════════════════════════════════════════════════\n\n    /// @notice Returns message's encoded header field.\n    function header(Message message) internal pure returns (Header) {\n        return HeaderLib.wrapPadded((message.unwrap().indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH})));\n    }\n\n    /// @notice Returns message's body field as an untyped memory view.\n    function body(Message message) internal pure returns (MemView) {\n        MemView memView = message.unwrap();\n        return _body(memView);\n    }\n\n    // ══════════════════════════════════════════════ PRIVATE HELPERS ══════════════════════════════════════════════════\n\n    /// @dev Returns message's padded header without checking that it is a valid header.\n    function _header(MemView memView) private pure returns (uint256) {\n        return memView.indexUint({index_: OFFSET_HEADER, bytes_: HEADER_LENGTH});\n    }\n\n    /// @dev Returns an untyped memory view over the body field without checking\n    /// if the whole payload or the body are properly formatted.\n    function _body(MemView memView) private pure returns (MemView) {\n        return memView.sliceFrom({index_: OFFSET_BODY});\n    }\n}\n\n// contracts/base/AgentSecured.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/**\n * @notice Base contract for messaging contracts that are secured by the agent manager.\n * `AgentSecured` relies on `AgentManager` to provide the following functionality:\n * - Keep track of agents and their statuses.\n * - Pass agent-signed statements that were verified by the agent manager.\n * - These statements are considered valid indefinitely, unless the agent is disputed.\n * - Disputes are opened and resolved by the agent manager.\n * \u003e `AgentSecured` implementation should never use statements signed by agents that are disputed.\n */\nabstract contract AgentSecured is MessagingBase, IAgentSecured {\n    // ════════════════════════════════════════════════ IMMUTABLES ═════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    address public immutable agentManager;\n\n    /// @inheritdoc IAgentSecured\n    address public immutable inbox;\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    // (agent index =\u003e their dispute status: flag, openedAt, resolvedAt)\n    mapping(uint32 =\u003e DisputeStatus) internal _disputes;\n\n    /// @dev gap for upgrade safety\n    uint256[49] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    modifier onlyAgentManager() {\n        if (msg.sender != agentManager) revert CallerNotAgentManager();\n        _;\n    }\n\n    modifier onlyInbox() {\n        if (msg.sender != inbox) revert CallerNotInbox();\n        _;\n    }\n\n    constructor(string memory version_, uint32 synapseDomain_, address agentManager_, address inbox_)\n        MessagingBase(version_, synapseDomain_)\n    {\n        agentManager = agentManager_;\n        inbox = inbox_;\n    }\n\n    // ════════════════════════════════════════════ ONLY AGENT MANAGER ═════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function openDispute(uint32 guardIndex, uint32 notaryIndex) external onlyAgentManager {\n        uint40 openedAt = ChainContext.blockTimestamp();\n        DisputeStatus memory status = DisputeStatus({flag: DisputeFlag.Pending, openedAt: openedAt, resolvedAt: 0});\n        _disputes[guardIndex] = status;\n        _disputes[notaryIndex] = status;\n    }\n\n    /// @inheritdoc IAgentSecured\n    function resolveDispute(uint32 slashedIndex, uint32 rivalIndex) external onlyAgentManager {\n        // Update the dispute status of the slashed agent first.\n        uint40 resolvedAt = ChainContext.blockTimestamp();\n        _disputes[slashedIndex].flag = DisputeFlag.Slashed;\n        _disputes[slashedIndex].resolvedAt = resolvedAt;\n        // Mark the rival agent as not disputed, if there was an ongoing dispute.\n        if (rivalIndex != 0) {\n            _disputes[rivalIndex].flag = DisputeFlag.None;\n            _disputes[rivalIndex].resolvedAt = resolvedAt;\n        }\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IAgentSecured\n    function agentStatus(address agent) external view returns (AgentStatus memory) {\n        return _agentStatus(agent);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function getAgent(uint256 index) external view returns (address agent, AgentStatus memory status) {\n        return _getAgent(index);\n    }\n\n    /// @inheritdoc IAgentSecured\n    function latestDisputeStatus(uint32 agentIndex) external view returns (DisputeStatus memory) {\n        return _disputes[agentIndex];\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns status of the given agent: (flag, domain, index).\n    function _agentStatus(address agent) internal view returns (AgentStatus memory) {\n        return IAgentManager(agentManager).agentStatus(agent);\n    }\n\n    /// @dev Returns agent and their status for a given agent index. Returns zero values for non existing indexes.\n    function _getAgent(uint256 index) internal view returns (address agent, AgentStatus memory status) {\n        return IAgentManager(agentManager).getAgent(index);\n    }\n\n    /// @dev Checks if a Dispute exists for the given Notary. This function returns true, if\n    /// Notary is in ongoing Dispute, or if Dispute was resolved not in Notary's favor.\n    /// In both cases we can't trust Notary's data.\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeExists(uint32 notaryIndex) internal view returns (bool) {\n        return _disputes[notaryIndex].flag != DisputeFlag.None;\n    }\n\n    /// @dev Checks if a Notary recently won a Dispute and is still in the \"post-dispute\" timeout period.\n    /// In this period we still can't trust Notary's data, though we can optimistically assume that\n    /// that the data will be correct after the timeout (assuming no new Disputes are opened).\n    /// Note: Agent-Secured contracts can trust Notary data only if both `_notaryDisputeExists` and\n    /// `_notaryDisputeTimeout` return false.\n    function _notaryDisputeTimeout(uint32 notaryIndex) internal view returns (bool) {\n        DisputeStatus memory status = _disputes[notaryIndex];\n        // Exit early if Notary is in ongoing Dispute / slashed.\n        if (status.flag != DisputeFlag.None) return false;\n        // Check if Notary has been in any Dispute at all.\n        if (status.openedAt == 0) return false;\n        // Otherwise check if the Dispute timeout is still active.\n        return block.timestamp \u003c status.resolvedAt + DISPUTE_TIMEOUT_NOTARY;\n    }\n}\n\n// contracts/hubs/StateHub.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StateHub` is a parent contract for `Origin`. It is responsible for the following:\n/// - Keeping track of the historical Origin Merkle Tree containing all the message hashes.\n/// - Keeping track of the historical Origin States, as well as verifying their validity.\nabstract contract StateHub is AgentSecured, StateHubEvents, IStateHub {\n    using SafeCast for uint256;\n    using StateLib for bytes;\n\n    struct OriginState {\n        uint40 blockNumber;\n        uint40 timestamp;\n        GasData gasData;\n    }\n    // Bits left for tight packing: 80\n\n    // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n    /// @dev Historical Merkle Tree\n    /// Note: Takes two storage slots\n    HistoricalTree private _tree;\n\n    /// @dev All historical contract States\n    OriginState[] private _originStates;\n\n    /// @dev gap for upgrade safety\n    uint256[47] private __GAP; // solhint-disable-line var-name-mixedcase\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc IStateHub\n    function isValidState(bytes memory statePayload) external view returns (bool isValid) {\n        // This will revert if payload is not a formatted state\n        State state = statePayload.castToState();\n        return _isValidState(state);\n    }\n\n    /// @inheritdoc IStateHub\n    function statesAmount() external view returns (uint256) {\n        return _originStates.length;\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestLatestState() external view returns (bytes memory stateData) {\n        // This never underflows, assuming the contract was initialized\n        return suggestState(_nextNonce() - 1);\n    }\n\n    /// @inheritdoc IStateHub\n    function suggestState(uint32 nonce) public view returns (bytes memory stateData) {\n        // This will revert if nonce is out of range\n        bytes32 root = _tree.root(nonce);\n        return _formatOriginState(_originStates[nonce], root, localDomain, nonce);\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Initializes the saved states list by inserting a state for an empty Merkle Tree.\n    function _initializeStates() internal {\n        // This should only be called once, when the contract is initialized\n        // This will revert if _tree.roots is non-empty\n        bytes32 savedRoot = _tree.initializeRoots();\n        // Save root for empty merkle _tree with block number and timestamp of initialization\n        _saveState(savedRoot, _toOriginState());\n    }\n\n    /// @dev Inserts leaf into the Merkle Tree and saves the updated origin State.\n    function _insertAndSave(bytes32 leaf) internal {\n        bytes32 newRoot = _tree.insert(leaf);\n        _saveState(newRoot, _toOriginState());\n    }\n\n    /// @dev Saves an updated state of the Origin contract\n    function _saveState(bytes32 root, OriginState memory state) internal {\n        uint32 nonce = _nextNonce();\n        _originStates.push(state);\n        // Emit event with raw state data\n        emit StateSaved(_formatOriginState(state, root, localDomain, nonce));\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n    /// @dev Returns nonce of the next sent message: the amount of saved States so far.\n    /// This always equals to \"total amount of sent messages\" plus 1.\n    function _nextNonce() internal view returns (uint32) {\n        // TODO: consider using more than 32 bits for origin nonces\n        return _originStates.length.toUint32();\n    }\n\n    /// @dev Checks if a state is valid, i.e. if it matches the historical one.\n    /// Reverts, if state refers to another Origin contract.\n    function _isValidState(State state) internal view returns (bool) {\n        // Check if state refers to this contract\n        if (state.origin() != localDomain) revert IncorrectOriginDomain();\n        // Check if nonce exists\n        uint32 nonce = state.nonce();\n        if (nonce \u003e= _originStates.length) return false;\n        // Check if state root matches the historical one\n        if (state.root() != _tree.root(nonce)) return false;\n        // Check if state metadata matches the historical one\n        return _areEqual(state, _originStates[nonce]);\n    }\n\n    // ═════════════════════════════════════════════ STRUCT FORMATTING ═════════════════════════════════════════════════\n\n    /// @dev Returns a formatted payload for a stored OriginState.\n    function _formatOriginState(OriginState memory originState, bytes32 root, uint32 origin, uint32 nonce)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return StateLib.formatState({\n            root_: root,\n            origin_: origin,\n            nonce_: nonce,\n            blockNumber_: originState.blockNumber,\n            timestamp_: originState.timestamp,\n            gasData_: originState.gasData\n        });\n    }\n\n    /// @dev Child contract should implement the logic for getting the current gas data from the gas oracle\n    /// to be saved as part of the Origin State.\n    // solhint-disable-next-line ordering\n    function _fetchGasData() internal view virtual returns (GasData);\n\n    /// @dev Returns a OriginState struct to save in the contract.\n    function _toOriginState() internal view returns (OriginState memory originState) {\n        originState.blockNumber = ChainContext.blockNumber();\n        originState.timestamp = ChainContext.blockTimestamp();\n        originState.gasData = _fetchGasData();\n    }\n\n    /// @dev Checks that a state and its Origin representation are equal.\n    function _areEqual(State state, OriginState memory originState) internal pure returns (bool) {\n        return state.blockNumber() == originState.blockNumber \u0026\u0026 state.timestamp() == originState.timestamp;\n    }\n}\n\n// contracts/Origin.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Origin` contract is used for sending messages to remote chains. It is done\n/// by inserting the message hashes into the Origin Merkle, which makes it possible to\n/// prove that message was sent using the Merkle proof against the Origin Merkle Root. This essentially\n/// compresses the list of messages into a single 32-byte value that needs to be stored on the destination chain.\n/// `Origin` is responsible for the following:\n/// - Formatting the sent message payloads, and inserting their hashes into the Origin Merkle Tree.\n/// - Keeping track of its own historical states (see parent contract `StateHub`).\n/// - Enforcing minimum tip values for sent base messages based on the provided execution requests.\n/// - Distributing the collected tips upon request from a local `AgentManager` contract.\ncontract Origin is StateHub, OriginEvents, InterfaceOrigin {\n    using MemViewLib for bytes;\n    using MessageLib for bytes;\n    using TipsLib for bytes;\n    using TypeCasts for address;\n\n    address public immutable gasOracle;\n\n    modifier onlyRemoteDestination(uint32 destination) {\n        if (destination == localDomain) revert IncorrectDestinationDomain();\n        _;\n    }\n\n    // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n    // solhint-disable-next-line no-empty-blocks\n    constructor(uint32 synapseDomain_, address agentManager_, address inbox_, address gasOracle_)\n        AgentSecured(\"0.0.3\", synapseDomain_, agentManager_, inbox_)\n    {\n        gasOracle = gasOracle_;\n    }\n\n    /// @notice Initializes Origin contract:\n    /// - msg.sender is set as contract owner\n    /// - State of \"empty merkle tree\" is saved\n    function initialize() external initializer {\n        // Initialize Ownable: msg.sender is set as \"owner\"\n        __Ownable2Step_init();\n        // Initialize \"states\": state of an \"empty merkle tree\" is saved\n        _initializeStates();\n    }\n\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable onlyRemoteDestination(destination) returns (uint32 messageNonce, bytes32 messageHash) {\n        // Check that content is not too large\n        if (content.length \u003e MAX_CONTENT_BYTES) revert ContentLengthTooBig();\n        // This will revert if msg.value is lower than value of minimum tips\n        Tips tips = _getMinimumTips(destination, paddedRequest, content.length).matchValue(msg.value);\n        Request request = RequestLib.wrapPadded(paddedRequest);\n        // Format the BaseMessage body\n        bytes memory body = BaseMessageLib.formatBaseMessage({\n            sender_: msg.sender.addressToBytes32(),\n            recipient_: recipient,\n            tips_: tips,\n            request_: request,\n            content_: content\n        });\n        // Send the message\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Base, body);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        onlyAgentManager\n        onlyRemoteDestination(destination)\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // AgentManager (checked via modifier) is responsible for constructing the calldata payload correctly.\n        return _sendMessage(destination, optimisticPeriod, MessageFlag.Manager, payload);\n    }\n\n    /// @inheritdoc InterfaceOrigin\n    function withdrawTips(address recipient, uint256 amount) external onlyAgentManager {\n        if (address(this).balance \u003c amount) revert InsufficientEthBalance();\n        (bool success,) = recipient.call{value: amount}(\"\");\n        if (!success) revert EthTransferFailed();\n        emit TipWithdrawalCompleted(recipient, amount);\n    }\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /// @inheritdoc InterfaceOrigin\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue)\n    {\n        return _getMinimumTips(destination, paddedRequest, contentLength).value();\n    }\n\n    // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n    /// @dev Sends the given message to the specified destination. Message hash is inserted\n    /// into the Origin Merkle Tree, which will enable message execution on destination chain.\n    function _sendMessage(uint32 destination, uint32 optimisticPeriod, MessageFlag flag, bytes memory body)\n        internal\n        returns (uint32 messageNonce, bytes32 messageHash)\n    {\n        // Format the message header\n        messageNonce = _nextNonce();\n        Header header = flag.encodeHeader({\n            origin_: localDomain,\n            nonce_: messageNonce,\n            destination_: destination,\n            optimisticPeriod_: optimisticPeriod\n        });\n        // Format the full message payload\n        bytes memory msgPayload = MessageLib.formatMessage(header, body);\n        // Insert new leaf into the Origin Merkle Tree and save the updated state\n        messageHash = msgPayload.castToMessage().leaf();\n        _insertAndSave(messageHash);\n        // Emit event with message information\n        emit Sent(messageHash, messageNonce, destination, msgPayload);\n        // Update the gas oracle data. We do this after the provided tips are checked so that\n        // the provided message is sent in the event that the gas oracle data is updated to a higher value.\n        InterfaceGasOracle(gasOracle).updateGasData(destination);\n        // TODO: consider doing this before the message is sent, while adjusting GasOracle.getMinimumTips() to\n        // use the pending gas oracle data.\n    }\n\n    /// @dev Returns the minimum tips for sending a message to the given destination with the given request and content.\n    function _getMinimumTips(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        internal\n        view\n        returns (Tips)\n    {\n        return\n            TipsLib.wrapPadded(InterfaceGasOracle(gasOracle).getMinimumTips(destination, paddedRequest, contentLength));\n    }\n\n    /// @dev Gets the current gas data from the gas oracle to be saved as part of the Origin State.\n    function _fetchGasData() internal view override returns (GasData) {\n        return GasDataLib.wrapGasData(InterfaceGasOracle(gasOracle).getGasData());\n    }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[],"name":"IncorrectVersionLength","type":"error"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"versionString","type":"string"}],"stateMutability":"view","type":"function"}],"userDoc":{"kind":"user","methods":{},"notice":"Version getter for contracts. Doesn't use any storage slots, meaning it will never cause any troubles with the upgradeable contracts. For instance, this contract can be added or removed from the inheritance chain without shifting the storage layout.","version":1},"developerDoc":{"kind":"dev","methods":{},"stateVariables":{"_data":{"details":"Bytes representation of the \"version string\". Strings with length over 32 are not supported!"},"_length":{"details":"Length of the \"version string\""}},"title":"Versioned","version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"IncorrectVersionLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"versionString\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"stateVariables\":{\"_data\":{\"details\":\"Bytes representation of the \\\"version string\\\". Strings with length over 32 are not supported!\"},\"_length\":{\"details\":\"Length of the \\\"version string\\\"\"}},\"title\":\"Versioned\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"Version getter for contracts. Doesn't use any storage slots, meaning it will never cause any troubles with the upgradeable contracts. For instance, this contract can be added or removed from the inheritance chain without shifting the storage layout.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Origin.sol\":\"Versioned\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Origin.sol\":{\"keccak256\":\"0x96775924f147f3d1f8df8cdf56731fe52a15af8d8e12e608efb8158c112b18cd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e642a27f5fab3c62b4c02e9754e9e42b1cf2e5381dbea9d3d106d23b7772ebe6\",\"dweb:/ipfs/QmUwn7ZyBvPkjnMuK8ZMSexBUdNQnVtxwyoAyT4DXLQjra\"]}},\"version\":1}"},"hashes":{"version()":"54fd4d50"}}}